aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ode-0.9/ode
diff options
context:
space:
mode:
authordan miller2007-10-19 05:20:07 +0000
committerdan miller2007-10-19 05:20:07 +0000
commitfca74b0bf0a0833f5701e9c0de7b3bc15b2233dd (patch)
tree51bcae7a1b8381a6bf6fd8025a7de1e30fe0045d /libraries/ode-0.9/ode
parentresubmitting ode (diff)
downloadopensim-SC_OLD-fca74b0bf0a0833f5701e9c0de7b3bc15b2233dd.zip
opensim-SC_OLD-fca74b0bf0a0833f5701e9c0de7b3bc15b2233dd.tar.gz
opensim-SC_OLD-fca74b0bf0a0833f5701e9c0de7b3bc15b2233dd.tar.bz2
opensim-SC_OLD-fca74b0bf0a0833f5701e9c0de7b3bc15b2233dd.tar.xz
dont ask
Diffstat (limited to 'libraries/ode-0.9/ode')
-rw-r--r--libraries/ode-0.9/ode/Makefile.am4
-rw-r--r--libraries/ode-0.9/ode/Makefile.in489
-rw-r--r--libraries/ode-0.9/ode/README158
-rw-r--r--libraries/ode-0.9/ode/TODO698
-rw-r--r--libraries/ode-0.9/ode/demo/Makefile.am254
-rw-r--r--libraries/ode-0.9/ode/demo/Makefile.in953
-rw-r--r--libraries/ode-0.9/ode/demo/basket_geom.h13
-rw-r--r--libraries/ode-0.9/ode/demo/demo_I.cpp254
-rw-r--r--libraries/ode-0.9/ode/demo/demo_basket.cpp278
-rw-r--r--libraries/ode-0.9/ode/demo/demo_boxstack.cpp577
-rw-r--r--libraries/ode-0.9/ode/demo/demo_buggy.cpp325
-rw-r--r--libraries/ode-0.9/ode/demo/demo_chain1.c171
-rw-r--r--libraries/ode-0.9/ode/demo/demo_chain2.cpp165
-rw-r--r--libraries/ode-0.9/ode/demo/demo_collision.cpp1371
-rw-r--r--libraries/ode-0.9/ode/demo/demo_convex_cd.cpp195
-rw-r--r--libraries/ode-0.9/ode/demo/demo_crash.cpp635
-rw-r--r--libraries/ode-0.9/ode/demo/demo_cyl.cpp318
-rw-r--r--libraries/ode-0.9/ode/demo/demo_cylvssphere.cpp238
-rw-r--r--libraries/ode-0.9/ode/demo/demo_feedback.cpp314
-rw-r--r--libraries/ode-0.9/ode/demo/demo_friction.cpp206
-rw-r--r--libraries/ode-0.9/ode/demo/demo_heightfield.cpp2132
-rw-r--r--libraries/ode-0.9/ode/demo/demo_hinge.cpp166
-rw-r--r--libraries/ode-0.9/ode/demo/demo_jointPR.cpp377
-rw-r--r--libraries/ode-0.9/ode/demo/demo_joints.cpp1092
-rw-r--r--libraries/ode-0.9/ode/demo/demo_motor.cpp210
-rw-r--r--libraries/ode-0.9/ode/demo/demo_moving_trimesh.cpp1944
-rw-r--r--libraries/ode-0.9/ode/demo/demo_ode.cpp1128
-rw-r--r--libraries/ode-0.9/ode/demo/demo_plane2d.cpp268
-rw-r--r--libraries/ode-0.9/ode/demo/demo_slider.cpp172
-rw-r--r--libraries/ode-0.9/ode/demo/demo_space.cpp233
-rw-r--r--libraries/ode-0.9/ode/demo/demo_space_stress.cpp435
-rw-r--r--libraries/ode-0.9/ode/demo/demo_step.cpp193
-rw-r--r--libraries/ode-0.9/ode/demo/demo_trimesh.cpp537
-rw-r--r--libraries/ode-0.9/ode/demo/world_geom3.h9
-rw-r--r--libraries/ode-0.9/ode/doc/Doxyfile1237
-rw-r--r--libraries/ode-0.9/ode/doc/main.dox22
-rw-r--r--libraries/ode-0.9/ode/doc/pix/amotor.jpgbin13977 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/ball-and-socket-bad.jpgbin9129 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/ball-and-socket.jpgbin10284 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/body.jpgbin15133 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/contact.jpgbin12368 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/hinge.jpgbin10548 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/hinge2.jpgbin14083 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/joints.jpgbin8637 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/rollingcontact.jpgbin12402 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/sf-graph1.jpgbin28191 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/sf-graph2.jpgbin24694 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/slider.jpgbin10276 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/doc/pix/universal.jpgbin13309 -> 0 bytes
-rw-r--r--libraries/ode-0.9/ode/src/Makefile.am207
-rw-r--r--libraries/ode-0.9/ode/src/Makefile.in2290
-rw-r--r--libraries/ode-0.9/ode/src/array.cpp80
-rw-r--r--libraries/ode-0.9/ode/src/array.h135
-rw-r--r--libraries/ode-0.9/ode/src/box.cpp847
-rw-r--r--libraries/ode-0.9/ode/src/capsule.cpp369
-rw-r--r--libraries/ode-0.9/ode/src/collision_cylinder_box.cpp1007
-rw-r--r--libraries/ode-0.9/ode/src/collision_cylinder_plane.cpp254
-rw-r--r--libraries/ode-0.9/ode/src/collision_cylinder_sphere.cpp264
-rw-r--r--libraries/ode-0.9/ode/src/collision_cylinder_trimesh.cpp1145
-rw-r--r--libraries/ode-0.9/ode/src/collision_kernel.cpp1103
-rw-r--r--libraries/ode-0.9/ode/src/collision_kernel.h214
-rw-r--r--libraries/ode-0.9/ode/src/collision_quadtreespace.cpp584
-rw-r--r--libraries/ode-0.9/ode/src/collision_space.cpp790
-rw-r--r--libraries/ode-0.9/ode/src/collision_space_internal.h84
-rw-r--r--libraries/ode-0.9/ode/src/collision_std.h172
-rw-r--r--libraries/ode-0.9/ode/src/collision_transform.cpp232
-rw-r--r--libraries/ode-0.9/ode/src/collision_transform.h40
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_box.cpp1497
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp1181
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_distance.cpp1255
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_gimpact.cpp456
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_internal.h495
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_opcode.cpp833
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_plane.cpp213
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_ray.cpp198
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_sphere.cpp573
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_trimesh.cpp2033
-rw-r--r--libraries/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp1304
-rw-r--r--libraries/ode-0.9/ode/src/collision_util.cpp612
-rw-r--r--libraries/ode-0.9/ode/src/collision_util.h340
-rw-r--r--libraries/ode-0.9/ode/src/convex.cpp1294
-rw-r--r--libraries/ode-0.9/ode/src/cylinder.cpp100
-rw-r--r--libraries/ode-0.9/ode/src/error.cpp172
-rw-r--r--libraries/ode-0.9/ode/src/export-dif.cpp568
-rw-r--r--libraries/ode-0.9/ode/src/fastdot.c30
-rw-r--r--libraries/ode-0.9/ode/src/fastldlt.c381
-rw-r--r--libraries/ode-0.9/ode/src/fastlsolve.c298
-rw-r--r--libraries/ode-0.9/ode/src/fastltsolve.c199
-rw-r--r--libraries/ode-0.9/ode/src/heightfield.cpp1812
-rw-r--r--libraries/ode-0.9/ode/src/heightfield.h225
-rw-r--r--libraries/ode-0.9/ode/src/joint.cpp4065
-rw-r--r--libraries/ode-0.9/ode/src/joint.h346
-rw-r--r--libraries/ode-0.9/ode/src/lcp.cpp2007
-rw-r--r--libraries/ode-0.9/ode/src/lcp.h58
-rw-r--r--libraries/ode-0.9/ode/src/mass.cpp529
-rw-r--r--libraries/ode-0.9/ode/src/mat.cpp230
-rw-r--r--libraries/ode-0.9/ode/src/mat.h71
-rw-r--r--libraries/ode-0.9/ode/src/matrix.cpp358
-rw-r--r--libraries/ode-0.9/ode/src/memory.cpp87
-rw-r--r--libraries/ode-0.9/ode/src/misc.cpp169
-rw-r--r--libraries/ode-0.9/ode/src/objects.h138
-rw-r--r--libraries/ode-0.9/ode/src/obstack.cpp130
-rw-r--r--libraries/ode-0.9/ode/src/obstack.h68
-rw-r--r--libraries/ode-0.9/ode/src/ode.cpp1732
-rw-r--r--libraries/ode-0.9/ode/src/odemath.cpp178
-rw-r--r--libraries/ode-0.9/ode/src/plane.cpp145
-rw-r--r--libraries/ode-0.9/ode/src/quickstep.cpp880
-rw-r--r--libraries/ode-0.9/ode/src/quickstep.h33
-rw-r--r--libraries/ode-0.9/ode/src/ray.cpp686
-rw-r--r--libraries/ode-0.9/ode/src/rotation.cpp316
-rw-r--r--libraries/ode-0.9/ode/src/scrapbook.cpp485
-rw-r--r--libraries/ode-0.9/ode/src/sphere.cpp241
-rw-r--r--libraries/ode-0.9/ode/src/stack.cpp114
-rw-r--r--libraries/ode-0.9/ode/src/stack.h138
-rw-r--r--libraries/ode-0.9/ode/src/step.cpp1795
-rw-r--r--libraries/ode-0.9/ode/src/step.h36
-rwxr-xr-xlibraries/ode-0.9/ode/src/stepfast.cpp1139
-rw-r--r--libraries/ode-0.9/ode/src/testing.cpp243
-rw-r--r--libraries/ode-0.9/ode/src/testing.h65
-rw-r--r--libraries/ode-0.9/ode/src/timer.cpp421
-rw-r--r--libraries/ode-0.9/ode/src/util.cpp374
-rw-r--r--libraries/ode-0.9/ode/src/util.h38
122 files changed, 0 insertions, 60972 deletions
diff --git a/libraries/ode-0.9/ode/Makefile.am b/libraries/ode-0.9/ode/Makefile.am
deleted file mode 100644
index 5c9708e..0000000
--- a/libraries/ode-0.9/ode/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
1SUBDIRS = src
2if ENABLE_DEMOS
3 SUBDIRS += demo
4endif
diff --git a/libraries/ode-0.9/ode/Makefile.in b/libraries/ode-0.9/ode/Makefile.in
deleted file mode 100644
index d89db18..0000000
--- a/libraries/ode-0.9/ode/Makefile.in
+++ /dev/null
@@ -1,489 +0,0 @@
1# Makefile.in generated by automake 1.10 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
6# This Makefile.in is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13# PARTICULAR PURPOSE.
14
15@SET_MAKE@
16VPATH = @srcdir@
17pkgdatadir = $(datadir)/@PACKAGE@
18pkglibdir = $(libdir)/@PACKAGE@
19pkgincludedir = $(includedir)/@PACKAGE@
20am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
21install_sh_DATA = $(install_sh) -c -m 644
22install_sh_PROGRAM = $(install_sh) -c
23install_sh_SCRIPT = $(install_sh) -c
24INSTALL_HEADER = $(INSTALL_DATA)
25transform = $(program_transform_name)
26NORMAL_INSTALL = :
27PRE_INSTALL = :
28POST_INSTALL = :
29NORMAL_UNINSTALL = :
30PRE_UNINSTALL = :
31POST_UNINSTALL = :
32build_triplet = @build@
33host_triplet = @host@
34target_triplet = @target@
35@ENABLE_DEMOS_TRUE@am__append_1 = demo
36subdir = ode
37DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in TODO
38ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
39am__aclocal_m4_deps = $(top_srcdir)/configure.in
40am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
41 $(ACLOCAL_M4)
42mkinstalldirs = $(install_sh) -d
43CONFIG_HEADER = $(top_builddir)/include/ode/config.h
44CONFIG_CLEAN_FILES =
45SOURCES =
46DIST_SOURCES =
47RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
48 html-recursive info-recursive install-data-recursive \
49 install-dvi-recursive install-exec-recursive \
50 install-html-recursive install-info-recursive \
51 install-pdf-recursive install-ps-recursive install-recursive \
52 installcheck-recursive installdirs-recursive pdf-recursive \
53 ps-recursive uninstall-recursive
54RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
55 distclean-recursive maintainer-clean-recursive
56ETAGS = etags
57CTAGS = ctags
58DIST_SUBDIRS = src demo
59DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
60ACLOCAL = @ACLOCAL@
61ALLOCA = @ALLOCA@
62AMTAR = @AMTAR@
63ARCHFLAGS = @ARCHFLAGS@
64AUTOCONF = @AUTOCONF@
65AUTOHEADER = @AUTOHEADER@
66AUTOMAKE = @AUTOMAKE@
67AWK = @AWK@
68CC = @CC@
69CCDEPMODE = @CCDEPMODE@
70CFLAGS = @CFLAGS@
71CPP = @CPP@
72CPPFLAGS = @CPPFLAGS@
73CXX = @CXX@
74CXXDEPMODE = @CXXDEPMODE@
75CXXFLAGS = @CXXFLAGS@
76CYGPATH_W = @CYGPATH_W@
77DEFS = @DEFS@
78DEPDIR = @DEPDIR@
79DRAWSTUFF = @DRAWSTUFF@
80ECHO_C = @ECHO_C@
81ECHO_N = @ECHO_N@
82ECHO_T = @ECHO_T@
83EGREP = @EGREP@
84EXEEXT = @EXEEXT@
85GL_LIBS = @GL_LIBS@
86GREP = @GREP@
87INSTALL = @INSTALL@
88INSTALL_DATA = @INSTALL_DATA@
89INSTALL_PROGRAM = @INSTALL_PROGRAM@
90INSTALL_SCRIPT = @INSTALL_SCRIPT@
91INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
92LDFLAGS = @LDFLAGS@
93LIBOBJS = @LIBOBJS@
94LIBS = @LIBS@
95LTLIBOBJS = @LTLIBOBJS@
96MAKEINFO = @MAKEINFO@
97MKDIR_P = @MKDIR_P@
98OBJEXT = @OBJEXT@
99ODE_AGE = @ODE_AGE@
100ODE_CURRENT = @ODE_CURRENT@
101ODE_RELEASE = @ODE_RELEASE@
102ODE_REVISION = @ODE_REVISION@
103ODE_SONAME = @ODE_SONAME@
104PACKAGE = @PACKAGE@
105PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
106PACKAGE_NAME = @PACKAGE_NAME@
107PACKAGE_STRING = @PACKAGE_STRING@
108PACKAGE_TARNAME = @PACKAGE_TARNAME@
109PACKAGE_VERSION = @PACKAGE_VERSION@
110PATH_SEPARATOR = @PATH_SEPARATOR@
111RANLIB = @RANLIB@
112SET_MAKE = @SET_MAKE@
113SHARED_LDFLAGS = @SHARED_LDFLAGS@
114SHELL = @SHELL@
115STRIP = @STRIP@
116TOPDIR = @TOPDIR@
117VERSION = @VERSION@
118WINDRES = @WINDRES@
119XMKMF = @XMKMF@
120X_CFLAGS = @X_CFLAGS@
121X_EXTRA_LIBS = @X_EXTRA_LIBS@
122X_LIBS = @X_LIBS@
123X_PRE_LIBS = @X_PRE_LIBS@
124abs_builddir = @abs_builddir@
125abs_srcdir = @abs_srcdir@
126abs_top_builddir = @abs_top_builddir@
127abs_top_srcdir = @abs_top_srcdir@
128ac_ct_CC = @ac_ct_CC@
129ac_ct_CXX = @ac_ct_CXX@
130ac_ct_WINDRES = @ac_ct_WINDRES@
131am__include = @am__include@
132am__leading_dot = @am__leading_dot@
133am__quote = @am__quote@
134am__tar = @am__tar@
135am__untar = @am__untar@
136bindir = @bindir@
137build = @build@
138build_alias = @build_alias@
139build_cpu = @build_cpu@
140build_os = @build_os@
141build_vendor = @build_vendor@
142builddir = @builddir@
143datadir = @datadir@
144datarootdir = @datarootdir@
145docdir = @docdir@
146dvidir = @dvidir@
147exec_prefix = @exec_prefix@
148host = @host@
149host_alias = @host_alias@
150host_cpu = @host_cpu@
151host_os = @host_os@
152host_vendor = @host_vendor@
153htmldir = @htmldir@
154includedir = @includedir@
155infodir = @infodir@
156install_sh = @install_sh@
157libdir = @libdir@
158libexecdir = @libexecdir@
159localedir = @localedir@
160localstatedir = @localstatedir@
161mandir = @mandir@
162mkdir_p = @mkdir_p@
163oldincludedir = @oldincludedir@
164pdfdir = @pdfdir@
165prefix = @prefix@
166program_transform_name = @program_transform_name@
167psdir = @psdir@
168sbindir = @sbindir@
169sharedstatedir = @sharedstatedir@
170so_ext = @so_ext@
171srcdir = @srcdir@
172sysconfdir = @sysconfdir@
173target = @target@
174target_alias = @target_alias@
175target_cpu = @target_cpu@
176target_os = @target_os@
177target_vendor = @target_vendor@
178top_builddir = @top_builddir@
179top_srcdir = @top_srcdir@
180SUBDIRS = src $(am__append_1)
181all: all-recursive
182
183.SUFFIXES:
184$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
185 @for dep in $?; do \
186 case '$(am__configure_deps)' in \
187 *$$dep*) \
188 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
189 && exit 0; \
190 exit 1;; \
191 esac; \
192 done; \
193 echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/Makefile'; \
194 cd $(top_srcdir) && \
195 $(AUTOMAKE) --foreign ode/Makefile
196.PRECIOUS: Makefile
197Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
198 @case '$?' in \
199 *config.status*) \
200 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
201 *) \
202 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
203 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
204 esac;
205
206$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
207 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
208
209$(top_srcdir)/configure: $(am__configure_deps)
210 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
211$(ACLOCAL_M4): $(am__aclocal_m4_deps)
212 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
213
214# This directory's subdirectories are mostly independent; you can cd
215# into them and run `make' without going through this Makefile.
216# To change the values of `make' variables: instead of editing Makefiles,
217# (1) if the variable is set in `config.status', edit `config.status'
218# (which will cause the Makefiles to be regenerated when you run `make');
219# (2) otherwise, pass the desired values on the `make' command line.
220$(RECURSIVE_TARGETS):
221 @failcom='exit 1'; \
222 for f in x $$MAKEFLAGS; do \
223 case $$f in \
224 *=* | --[!k]*);; \
225 *k*) failcom='fail=yes';; \
226 esac; \
227 done; \
228 dot_seen=no; \
229 target=`echo $@ | sed s/-recursive//`; \
230 list='$(SUBDIRS)'; for subdir in $$list; do \
231 echo "Making $$target in $$subdir"; \
232 if test "$$subdir" = "."; then \
233 dot_seen=yes; \
234 local_target="$$target-am"; \
235 else \
236 local_target="$$target"; \
237 fi; \
238 (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
239 || eval $$failcom; \
240 done; \
241 if test "$$dot_seen" = "no"; then \
242 $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
243 fi; test -z "$$fail"
244
245$(RECURSIVE_CLEAN_TARGETS):
246 @failcom='exit 1'; \
247 for f in x $$MAKEFLAGS; do \
248 case $$f in \
249 *=* | --[!k]*);; \
250 *k*) failcom='fail=yes';; \
251 esac; \
252 done; \
253 dot_seen=no; \
254 case "$@" in \
255 distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
256 *) list='$(SUBDIRS)' ;; \
257 esac; \
258 rev=''; for subdir in $$list; do \
259 if test "$$subdir" = "."; then :; else \
260 rev="$$subdir $$rev"; \
261 fi; \
262 done; \
263 rev="$$rev ."; \
264 target=`echo $@ | sed s/-recursive//`; \
265 for subdir in $$rev; do \
266 echo "Making $$target in $$subdir"; \
267 if test "$$subdir" = "."; then \
268 local_target="$$target-am"; \
269 else \
270 local_target="$$target"; \
271 fi; \
272 (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
273 || eval $$failcom; \
274 done && test -z "$$fail"
275tags-recursive:
276 list='$(SUBDIRS)'; for subdir in $$list; do \
277 test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
278 done
279ctags-recursive:
280 list='$(SUBDIRS)'; for subdir in $$list; do \
281 test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
282 done
283
284ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
285 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
286 unique=`for i in $$list; do \
287 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
288 done | \
289 $(AWK) ' { files[$$0] = 1; } \
290 END { for (i in files) print i; }'`; \
291 mkid -fID $$unique
292tags: TAGS
293
294TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
295 $(TAGS_FILES) $(LISP)
296 tags=; \
297 here=`pwd`; \
298 if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
299 include_option=--etags-include; \
300 empty_fix=.; \
301 else \
302 include_option=--include; \
303 empty_fix=; \
304 fi; \
305 list='$(SUBDIRS)'; for subdir in $$list; do \
306 if test "$$subdir" = .; then :; else \
307 test ! -f $$subdir/TAGS || \
308 tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
309 fi; \
310 done; \
311 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
312 unique=`for i in $$list; do \
313 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
314 done | \
315 $(AWK) ' { files[$$0] = 1; } \
316 END { for (i in files) print i; }'`; \
317 if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
318 test -n "$$unique" || unique=$$empty_fix; \
319 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
320 $$tags $$unique; \
321 fi
322ctags: CTAGS
323CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
324 $(TAGS_FILES) $(LISP)
325 tags=; \
326 here=`pwd`; \
327 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
328 unique=`for i in $$list; do \
329 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
330 done | \
331 $(AWK) ' { files[$$0] = 1; } \
332 END { for (i in files) print i; }'`; \
333 test -z "$(CTAGS_ARGS)$$tags$$unique" \
334 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
335 $$tags $$unique
336
337GTAGS:
338 here=`$(am__cd) $(top_builddir) && pwd` \
339 && cd $(top_srcdir) \
340 && gtags -i $(GTAGS_ARGS) $$here
341
342distclean-tags:
343 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
344
345distdir: $(DISTFILES)
346 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
347 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
348 list='$(DISTFILES)'; \
349 dist_files=`for file in $$list; do echo $$file; done | \
350 sed -e "s|^$$srcdirstrip/||;t" \
351 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
352 case $$dist_files in \
353 */*) $(MKDIR_P) `echo "$$dist_files" | \
354 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
355 sort -u` ;; \
356 esac; \
357 for file in $$dist_files; do \
358 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
359 if test -d $$d/$$file; then \
360 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
361 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
362 cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
363 fi; \
364 cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
365 else \
366 test -f $(distdir)/$$file \
367 || cp -p $$d/$$file $(distdir)/$$file \
368 || exit 1; \
369 fi; \
370 done
371 list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
372 if test "$$subdir" = .; then :; else \
373 test -d "$(distdir)/$$subdir" \
374 || $(MKDIR_P) "$(distdir)/$$subdir" \
375 || exit 1; \
376 distdir=`$(am__cd) $(distdir) && pwd`; \
377 top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
378 (cd $$subdir && \
379 $(MAKE) $(AM_MAKEFLAGS) \
380 top_distdir="$$top_distdir" \
381 distdir="$$distdir/$$subdir" \
382 am__remove_distdir=: \
383 am__skip_length_check=: \
384 distdir) \
385 || exit 1; \
386 fi; \
387 done
388check-am: all-am
389check: check-recursive
390all-am: Makefile
391installdirs: installdirs-recursive
392installdirs-am:
393install: install-recursive
394install-exec: install-exec-recursive
395install-data: install-data-recursive
396uninstall: uninstall-recursive
397
398install-am: all-am
399 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
400
401installcheck: installcheck-recursive
402install-strip:
403 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
404 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
405 `test -z '$(STRIP)' || \
406 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
407mostlyclean-generic:
408
409clean-generic:
410
411distclean-generic:
412 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
413
414maintainer-clean-generic:
415 @echo "This command is intended for maintainers to use"
416 @echo "it deletes files that may require special tools to rebuild."
417clean: clean-recursive
418
419clean-am: clean-generic mostlyclean-am
420
421distclean: distclean-recursive
422 -rm -f Makefile
423distclean-am: clean-am distclean-generic distclean-tags
424
425dvi: dvi-recursive
426
427dvi-am:
428
429html: html-recursive
430
431info: info-recursive
432
433info-am:
434
435install-data-am:
436
437install-dvi: install-dvi-recursive
438
439install-exec-am:
440
441install-html: install-html-recursive
442
443install-info: install-info-recursive
444
445install-man:
446
447install-pdf: install-pdf-recursive
448
449install-ps: install-ps-recursive
450
451installcheck-am:
452
453maintainer-clean: maintainer-clean-recursive
454 -rm -f Makefile
455maintainer-clean-am: distclean-am maintainer-clean-generic
456
457mostlyclean: mostlyclean-recursive
458
459mostlyclean-am: mostlyclean-generic
460
461pdf: pdf-recursive
462
463pdf-am:
464
465ps: ps-recursive
466
467ps-am:
468
469uninstall-am:
470
471.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
472 install-strip
473
474.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
475 all all-am check check-am clean clean-generic ctags \
476 ctags-recursive distclean distclean-generic distclean-tags \
477 distdir dvi dvi-am html html-am info info-am install \
478 install-am install-data install-data-am install-dvi \
479 install-dvi-am install-exec install-exec-am install-html \
480 install-html-am install-info install-info-am install-man \
481 install-pdf install-pdf-am install-ps install-ps-am \
482 install-strip installcheck installcheck-am installdirs \
483 installdirs-am maintainer-clean maintainer-clean-generic \
484 mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
485 tags-recursive uninstall uninstall-am
486
487# Tell versions [3.59,3.63) of GNU make to not export all variables.
488# Otherwise a system limit (for SysV at least) may be exceeded.
489.NOEXPORT:
diff --git a/libraries/ode-0.9/ode/README b/libraries/ode-0.9/ode/README
deleted file mode 100644
index dd4596f..0000000
--- a/libraries/ode-0.9/ode/README
+++ /dev/null
@@ -1,158 +0,0 @@
1Dynamics Library.
2=================
3
4CONVENTIONS
5-----------
6
7matrix storage
8--------------
9
10matrix operations like factorization are expensive, so we must store the data
11in a way that is most useful to the matrix code. we want the ability to update
12the dynamics library without recompiling applications, e.g. so users can take
13advantage of new floating point hardware. so we must settle on a single
14format. because of the prevalence of 4-way SIMD, the format is this: store
15the matrix by rows or columns, and each column is rounded up to a multiple of
164 elements. the extra "padding" elements at the end of each row/column are set
17to 0. this is called the "standard format". to indicate if the data is stored
18by rows or columns, we will say "standard row format" or "standard column
19format". hopefully this decision will remain good in the future, as more and
20more processors have 4-way SIMD, and 3D graphics always needs fast 4x4
21matrices.
22
23exception: matrices that have only one column or row (vectors), are always
24stored as consecutive elements in standard row format, i.e. there is no
25interior padding, only padding at the end.
26
27thus: all 3x1 floating point vectors are stored as 4x1 vectors: (x,x,x,0).
28also: all 6x1 spatial velocities and accelerations are split into 3x1 position
29 and angular components, which are stored as contiguous 4x1 vectors.
30
31ALL matrices are stored by in standard row format.
32
33
34arguments
35---------
36
373x1 vector arguments to set() functions are supplied as x,y,z.
383x1 vector result arguments to get() function are pointers to arrays.
39larger vectors are always supplied and returned as pointers.
40all coordinates are in the global frame except where otherwise specified.
41output-only arguments are usually supplied at the end.
42
43
44memory allocation
45-----------------
46
47with many C/C++ libraries memory allocation is a difficult problem to solve.
48who allocates the memory? who frees it? must objects go on the heap or can
49they go on the stack or in static storage? to provide the maximum flexibility,
50the dynamics and collision libraries do not do their own memory allocation.
51you must pass in pointers to externally allocated chunks of the right sizes.
52the body, joint and colllision object structures are all exported, so you
53can make instances of those structure and pass pointers to them.
54
55there are helper functions which allocate objects out of areans, in case you
56need loots of dynamic creation and deletion.
57
58BUT!!! this ties us down to the body/joint/collision representation.
59
60a better approach is to supply custom memory allocation functions
61(e.g. dlAlloc() etc).
62
63
64C versus C++ ... ?
65------------------
66
67everything should be C linkable, and there should be C header files for
68everything. but we want to develop in C++. so do this:
69 * all comments are "//". automatically convert to /**/ for distribution.
70 * structures derived from other structures --> automatically convert?
71
72
73WORLDS
74------
75
76might want better terminology here.
77
78the dynamics world (DWorld) is a list of systems. each system corresponds to
79one or more bodies, or perhaps some other kinds of physical object.
80each system corresponds to one or more objects in the collision world
81(there does not have to be a one-to-one correspondence between bodies and
82collision objects).
83
84systems are simulated separately, perhaps using completely different
85techniques. we must do something special when systems collide.
86systems collide when collision objects belonging to system A touch
87collision objects belonging to system B.
88
89for each collision point, the system must provide matrix equation data
90that is used to compute collision forces. once those forces are computed,
91the system must incorporate the forces into its timestep.
92PROBLEM: what if we intertwine the LCP problems of the two systems - then
93this simple approach wont work.
94
95the dynamics world contains two kinds of objects: bodies and joints.
96joints connect two bodies together.
97
98the world contains one of more partitions. each partition is a collection of
99bodies and joints such that each body is attached (through one or more joints)
100to every other body.
101
102Joints
103------
104
105a joint can be connected to one or two bodies.
106if the joint is only connected to one body, joint.node[1].body == 0.
107joint.node[0].body is always valid.
108
109
110Linkage
111-------
112
113this library will always be statically linked with the app, for these reasons:
114 * collision space is selected at compile time, it adds data to the geom
115 objects.
116
117
118Optimization
119------------
120
121doubles must be aligned on 8 byte boundaries!
122
123
124MinGW on Windows issues
125-----------------------
126
127* the .rc file for drawstuff needs a different include, try winresrc.h.
128
129* it seems we can't have both main() and WinMain() without the entry point
130 defaulting to main() and having resource loading problems. this screws up
131 what i was trying to do in the drawstuff library. perhaps main2() ?
132
133* remember to compile resources to COFF format RES files.
134
135
136
137Collision
138---------
139
140to plug in your own collision handling, replace (some of?) these functions
141with your own. collision should be a separate library that you can link in
142or not. your own library can call components in this collision library, e.g.
143if you want polymorphic spaces instead of a single statically called space.
144
145creating an object will automatically register the appropriate
146class (if necessary). how can we ensure that the minimum amount of code is
147linked in? e.g. only one space handler, and sphere-sphere and sphere-box and
148box-box collision code (if spheres and boxes instanced).
149
150the user creates a collision space, and for each dynamics object that is
151created a collision object is inserted into the space. the collision
152object's pos and R pointers are set to the corresponding dynamics
153variables.
154
155there should be utility functions which create the dynamics and collision
156objects at the same time, e.g. dMakeSphere().
157
158collision objects and dynamics objects keep pointers to each other.
diff --git a/libraries/ode-0.9/ode/TODO b/libraries/ode-0.9/ode/TODO
deleted file mode 100644
index cf6cdaa..0000000
--- a/libraries/ode-0.9/ode/TODO
+++ /dev/null
@@ -1,698 +0,0 @@
1
2@@@'s
3
4
5TODO for COLLISION
6------------------
7
8box-box collision: adjust generated face-face contact points by depth/2 to
9be more fair.
10
11what happens when a GeomTransform's encapsulated object is manipulated,
12e.g. position changed. should this be disallowed? should a GeomTransform
13behave like a space and propagate dirtyness upwards?
14
15make sure that when we are using a large space for static environmental geoms,
16that there is not excessive AABB computation when geoms are added/removed from
17the space. the space AABB is pretty much guaranteed to cover everything, so
18there's no need to compute/test the AABB in this case.
19
20hash space: implement collide2() efficiently instead of the current
21simple-space-like brute-force approach.
22
23hash space: incremental scheme, so we dont have to rebuild the data structures
24for geoms that don't move.
25
26disabled geoms (remove from all collision considerations) ... isn't this the
27same as just taking it out of its enclosing group/space?
28
29integrate:
30 dRay
31 triangle collider - get latest tri collider code from erwin
32 erwin's quadtree space
33
34tests:
35 all aspects of collision API
36
37 dGeomSetBody(0) maintains body-geom linked list properly.
38
39 simple space: instantiate lots of non-moving geoms (i.e. environmental
40 geoms and make sure that we're still able to collide efficiently.
41 make sure AABB computation is efficient, or can be made efficient
42 through proper use of the API.
43
44 test C interface support for making new classes.
45 make sure the dxGeom::aabbTest() function behaves as advertised.
46
47 testing for contact point consistency: test for things that
48 would cause the dynamics to fail or become unstable
49
50 test for: small adjustment in geom position causes a big jump in the
51 contact point set (bad for dynamics).
52
53 test for: if contact constraints observed then it's impossible
54 (or hard) to move the objects so that the penetration is
55 increased. relax this when only a subset of the contact points are
56 returned.
57
58 test for consistency, e.g. the boundary of geoms X and Y can
59 be defined by intersecting with a point, so test the intersection of X
60 and Y by comparing with the point tests.
61
62 check that contact points are in the collision volume
63
64 all existing space tests, and more.
65
66demos:
67 test_buggy: make a terrain out of non-moving geoms. use heirarchical
68 groups to get efficient collision, even with the simple space.
69
70go though the new collision docs and make sure the behavior that is described
71there is actually implemented.
72
73multi-resolution hash table:
74 the current implementation rebuilds a new hash table each time
75 collide() is called. we don't keep any state between calls. this is
76 wasteful if there are unmoving objects in the space.
77
78 make sure we prevent multiple collision callbacks for the same pair
79
80 better virtual address function.
81
82 the collision search can perhaps be optimized - as we search
83 chains we can come across other candidate intersections at
84 other levels, perhaps we should do the intersection check
85 straight away? --> save on list searching time only, which is
86 not too significant.
87
88collision docs:
89 optimization guide: whenever a single geom changes in a simple space,
90 the space AABB has to be recomputed by examining EVERY geom.
91 document this, or find a better behavior.
92
93
94
95TODO BEFORE NEXT RELEASE
96------------------------
97
98g++ needed for compiling tests using gcc 3.2 ? what is the problem?
99
100add joint feedback info from lambda, so that we can get motor forces etc.
101need a way to map constraint indexes to what they mean.
102
103track down and fix the occasional popping/jumping problem in test_boxstack,
104especially when boxes are piled on top of each other. find out if this is
105caused by a configuration singularity or whether there is a bug in LCP.
106i need to add some kind of diagnostic tool to help resolve these kinds of
107problems.
108
109fixup ground plane jitter and shadow jumping in drawstuff.
110
111the inertias/COMs don't appear to be totally correct for the boxstack demo.
112fix up, and add a mode that shows the effective mass box (for a given density).
113
114Improve box-box collision, especially for face-face contact (3 contact points).
115Improve cylinder-box collision (2 contact points).
116
117windows DLL building and unix shared libs. libtool?
118also MSVC project files.
119
120dBodyGetPointVel()
121
122contrib directory - all stuff in ~/3/ode
123
124functions to allow systems to be copied/cloned
125 dBodyTransplant (b, world)
126 dTransplantIsland (b, world)
127 dBodyCopy (bdest, bsrc)
128 dJointCopy (jdest, jsrc) -- what about body connections?
129 dCloneBody()
130 dCloneJoint()
131 dCloseBodyAndJointList()
132 dCloneIsland()
133
134this collision rule:
135 // no contacts if both geoms on the same body, and the body is not 0
136 if (g1->body == g2->body && g1->body) return 0;
137needs to be replaced. sometimes we want no collision when both bodies are 0,
138but this wont work for geomgroup-to-environment. avoid stupid stuff like
139 dGeomSetBody (geom_group, (dBodyID) 1);
140this also causes "failed-to-report" errors in the space test.
141
142Expose type-specific collision functions?
143
144Automatic code optimization process.
145
146joint limit spongyness: interacts with powered joints badly, because when the
147limit is reached full power is applied. fix or doc.
148
149various hinge2 functions may not function correctly if axis1 and axis2 are not
150perpendicular. in particular the getAngle() and getAngleRate() functions
151probably will give bogus answers.
152
153slow step function will not respect the joint getinfo2 functions calling
154addTorque() because it reads the force/torque accumulators before the
155getinfo2 functions are called.
156
157spaces need multiple lists of objects that can never overlap. objects in these
158lists are never tested against each other.
159
160deleting a body a joint is attached to should adjust the joint to only have
161one body attached. currently the connected joints have *both* their body
162attachments removed. BUT, dont do this if the dJOINT_TWOBODIES flag is set
163on the joint.
164
165document error, mem and math functions.
166
167Web pages
168 credits section
169 projects using ODE
170
171update C++ interface? use SWIG?
172
173collision exclusion groups - exclude if obj1.n == obj2.n ?
174
175make sure the amotor joint can be used with just one body. at the moment it
176only allows two-body attachments.
177
178implement dJointGetAMotorAngleRate()
179
180erwin says: Should the GeomGroup have a cleanupmode as the GeomTransform has?
181
182erwin says: http://q12.org/pipermail/ode/2002-January/000766.html
183 and http://q12.org/pipermail/ode/2001-December/000753.html
184
185rename duplicate filenames (object.h?) - some environments can't handle this.
186
187naming inconsistency: dCreateSphere() should be dSphereCreate() (etc...) to
188match the rest of the API.
189
190
191TODO
192----
193
194joint allocation in joint groups. allocation size should be rounded up using
195dEFFICIENT_SIZE, to properly align all the data members.
196
197all dAlloc() allocations should be aligned using dEFFICIENT_SIZE() ???
198
199automatic body & joint disabling / enabling.
200
201sometimes getting LCP infinite loops.
202
203function to get the entire island of bodies/joints
204
205joints:
206 hinge2 joint - implement trail, i.e. non-convergent steering and wheel
207 axes.
208
209 erp individually settable for each joint?
210
211 more joints:
212 angular3 (constrian full angle not position)
213 fixed path 1 (point must follow fixed path, etc etc)
214 - other fixed path joints.
215 linear a (point in 1 body fixed to plane of other)
216 linear b (point in 1 body fixed to line on other)
217 linear c (line in 1 body fixed to plane on other)
218 linear d (line in 1 body fixed to line on other) - like
219 prismatic but orientation along line can change
220 Relative-Path-Relative-Oriention Joint (set all dofs of 2
221 bodies relative to each other)
222 spring (with natural length)
223 universal (2 kinds)
224 various angular relationships
225
226 when attaching joints to static env, provision to move attachment
227 point (e.g. give it a linear/angular velocity). this can be used
228 instead of a FPFO joint on a body in many cases.
229 also do this with contacts to static env, to allow for contacts to
230 *moving* objects in the static env.
231
232 interpretation of erp: is it (1) the error reduction per timestep,
233 (2) or a time constant independent of timestep?? if it's (2) then
234 perhaps this should be universal - this is already the meaning for
235 the suspension.
236
237 hinge2 suspension:
238 suspension limits
239 suspension limit restitution and spongyness??
240
241use autoconf? set paths in makefile?
242
243no-arg init functions, for andy
244
245explore: do joint parameters need to be set for the joint to be setup
246correctly, or should set some proper body-dependent params when it is
247attached? this is only really an issue for joints that have no parameters to
248set, such as the fixed joint.
249
250dAlloc() should take an arena parameters which is stored in dWorld.
251
252debugging mode should use dASSERT2 that prints a descriptive error message
253on error, not just the file:line or function. use dASSERT for internal
254consistency checking.
255
256when vectors and matrices are initialized, we must ensure that the padding
257elements are set to 0. this is going to be a problem everywhere!
258
259don't use 3-vectors anywhere. use SIMD friendly 4-vectors.
260
261make sure all data in body/joint etc objects is aligned well for single
262precision SIMD (i.e. all vectors start on a 16 byte boundary).
263
264think about more complicated uses of collision, e.g. a single geom representing
265an articulated structure.
266
267bodyGroup? (like joint group but for bodies). systemGroup?
268
269check the overhead of resizing Array<>s as elements are pushed on to them.
270
271replace alloca() with dPushFrame(), dPopFrame(), and dAlloca() ? allow for
272the possibility of allocating in non-stack memory ?
273
274make sure that we can set mass parameters with non-zero center of mass.
275if this is done after the body position is set, the position is adjusted.
276if this is done before the body position is set, what do we do when the
277pos is set? does the pos always refer to the center of mass from the user's
278point of view?
279
280consider splitting solver into functions, which can be optimized separately.
281might make things go faster.
282
283faster code for islands with a single body? faster code for dynamically
284symmetric bodies?
285
286rotation.cpp functions that set matrices should also set padding elements.
287
288lcp solver must return (L,d) and some other information, so we can re-solve
289for other right hand sides later on, but using the same complimentarity
290solution so there are no integrator discontinuities.
291
292dSetZero() - make fast inline functions for fixed n e.g. (1-4).
293
294need proper `sticky' friction, i.e. compensation for numerical slip.
295
296on windows, make sure gcc-compiles libs can be linked with VC++ apps. need
297to make sure some C++ runtime bits are present?
298
299kill all references to dArray<> (in geom.cpp).
300
301need testing code to test all joints with body-to-static-env
302
303copy stack.cpp, memory.cpp stuff to reuse
304
305dFactorLDLT() is not so efficient for matrix sizes < block size, e.g.
306redundant calls, zero loads, adds etc
307
308contacts: cheaper friction: viscous friction? one step delay friction force.
309
310in geom.cpp, for objects that are never meant to collide, dCollide() will
311always try to find the collider functions, which wastes a bit of time.
312
313geom.cpp:dCollideG() - handle special case of colliding 2 groups more
314efficiently.
315
316timer reporting function:
317 void timerReport (void (*printFunction)(char *, ...));
318
319disabled bodies stored in a separate list, so they are never traversed at all,
320for speed when there are many disabled bodies.
321
322
323MAYBE
324-----
325
326new implementation for joint groups that is not so system dependent.
327maybe individual contacts are reusable? in this case contact information
328should be settable in the contact joints. max_size arg is really annoying.
329
330consider making anchor,axis, (everything) into a joint parameter and setting
331them with a consistent interface. also consider overload the joint functions
332so they are not distinguished by joint type??
333
334collision memory optimizations?
335
336collision: support for persistent contact information?
337
338multiply reference tri list data so that it can be cloned
339 if the tri-list geoms could support rot/pos
340 transformations then we could have several tri-lists pointing to the
341 same vertex information.
342
343height fields
344
345pre-converted collision data -- Creating a hash space and associated
346opcode tree structures may take significant amounts of time for a
347large world with many 10s of thousands of triangles. Any chance of
348pre-building that off-line and passing a memory block pointer to the
349collision system?
350
351putting objects in multiple spaces -- If it was possible to add
352objects to more than one space, you could do collision queries other
353than 1vsN and NvsN. That flexibility might be useful when you want to
354only collide against a subset of the space. For example, a camera
355system may want to collide some rays with occlusion walls but the
356occlusion walls may also need to be in the game-level space to bounce
357against.
358
359
360ALWAYS
361------
362
363make sure functions check their arguments in debug mode (e.g. using dASSERT).
364make sure joint/geom functions check for the specific object type.
365
366vectors alloca()ed on the stack must have the correct alignment, use ALLOCA16.
367
368library should have no global constructors, as it might be used with C linkage.
369
370use `const' in function arguments. blah.
371
372
373
374DON'T BOTHER
375------------
376
377warning if user tries to set mass params with nonzero center of mass.
378
379
380
381DONE
382----
383
384check: when contact attached with (body1,0) and (0,body1), check that polarity
385on depth and error info is okay for the two cases.
386
387set a better convention for which is the 1st and 2nd body in a joint, because
388sometimes we get things swapped (because of the way the joint nodes are used).
389
390hinge and prismatic, attachment to static environment.
391
392turn macros into C++ inline functions? what about C users?
393
394remove `space' argument to geom creation functions? make user add it?
395or just remove it from dCreateGeom() ? <-- did this one.
396
397test_chain should be in C, not C++. but first must remove global constructors.
398
399add more functionality to C++ interface - dMass, dSpace, dGeom
400
401there should be functions to delete groups of bodies/joints in one go - this
402will be more efficient than deleting them one at a time, because less
403partitioning tests will be needed.
404
405should we expose body and joint object structures so that the user can
406explicitly allocate them locally, or e.g. on the stack? makes allocating
407temporary contact constraints easier. NO --> helps data hiding and therefore
408library binary compatability.
409
410joints:
411 hinge & slider - DONE
412 measure angle, rate - DONE
413 power - DONE
414 joint limits - DONE
415 mixed powered+limited joints, powering away from limit - DONE
416
417 hinge2 - DONE
418 steering angle and rate measurement - DONE
419 steering limits - DONE
420 steering motor - DONE
421 wheel motor - DONE
422 wheel angle rate measurement - DONE
423
424 optional hinge2 suspension: - DONE
425 alignment of B&S part to given axis - DONE
426 global framework for giving epsilon and gamma - DONE
427
428 toss away r-motor, make power & stuff specific to joint - DONE
429 it's just easier that way
430
431 joint code reuse: - DONE
432 use standard functions to set velocity (c), limits (lo,hi),
433 spongyness (epsilon) etc, this prevents these functions from
434 proliferating
435
436 implicit spring framework - actually allow joints to return a value `k'
437 such that J*vnew = c + k*f, where f = force needed to achieve
438 vnew - DONE
439
440 contact slip - DONE
441 contact erp & cfm parameters (not just "softness") - DONE
442
443 hinge2: when we lock back wheels along the steering axis, there is no
444 error correction if they get out of alignment - DONE, just use high
445 and low limits.
446
447 joint limit spongyness: erp and cfm for joint set from world (global)
448 values when joint created. - DONE
449
450 joint limit restitution - DONE
451
452check inertia transformations, e.g. by applying steering torque to a thin
453wheel --> actually, i made test_I
454
455more comprehensive random number comparisons between slow and fast methods.
456 - random PD inertia (not just diagonal).
457 - random velocity
458 - random joint error (make joints then move bodies a bit)
459
460check that J*vnew=c (slow step already does this, but it doesn't equal zero
461for some reason! - actually, when LCP constraint limits are reached, it wont!)
462
463tons of things in lcp.cpp (@@@), especially speed optimizations. also, we
464wanted to do index block switching and index block updates to take advantage
465of the outer product trick ... but this is not worth the effort i think.
466
467lcp.cpp: if lo=hi=0, check operation. can we switch from NL <-> NH without
468going through C? --> done.
469
470andy says: still having trouble with those resource files..
471drawstuff.res doesn't seem to build or be found under cygwin gcc.
472
473DOC how bodies and geoms associated then resolved in contact callback ... not
474really necessary.
475
476fix the "memory leak" in geom.cpp
477
478library should have no global constructors, as it might be used with C linkage.
479 --> as long as test_chain1 works, there are none.
480
481DOC cfm, the derivation and what it means.
482 --> partially done, could be better
483
484joint "get type" function
485
486andy says: in ode/src/error.cpp _snprintf() and _vsnprintf() are missing
487in testode: finite and isnan are missing. copysign is missing
488 russ: okay here's the problem: i have Makefile.platform files for
489 VC++, MinGW, but not Cygwin. Cygwin uses the unix-like functions
490 for everything, but the VC++/MinGW configs assumes the MS C-runtime
491 functions. this is easy to fix, except i need to install Cygwin
492 which is a pain to do over MinGW. argh.
493
494build on linux - assumptions made about location of X11 lib, opengl etc.
495
496implement: dBodyAddForceAtPos,dBodyAddRelForceAtPos,dBodyAddRelForceAtRelPos,
497 dBodyGetPointPos,dBodyGetPointVel,dBodyGetPointRelVel
498
499dJointAttach(), allow both bodies to be 0 to put the joint into limbo.
500
501space near-callback should be given potentially intersecting objects 100 at a
502time instead of 1 at a time, to save on calling costs ... which are trivial,
503so we don't bother to do this.
504
505doccer: @func{} also refs second etc function in function *list*.
506
507make sure joints can return 0 from GetInfo1, i.e. no constraints or "inactive"
508joint, and the step functions will handle it.
509
510when attaching contact with (0,body), instead of setting the reverse flag
511on the joint and checking it in getInfo2(), we should just reverse the normal
512straight away ... ?
513 --> trouble is, dJointAttach() knows nothing about what kind of joint
514 it is attaching.
515
516hinge2 needs to be attached to two bodies for it to work, make sure this is
517always the case. --> assertion added in dJointAttach().
518
519if two joints connect to the same two bodies, check that the fast solver
520works! -> it should.
521
522functions to get all the joints/bodies a body/joint is connected to.
523
524If I don't have the GCC libraries installed, HUGE_VALF is undefined.
525
526fix capped cylinder - capped cylinder collision so that two contacts can
527be generated.
528
529transformation geometry object.
530
531joint groups should also be destroyed by destroying the world --> naaahhh.
532
533DONT DO THIS: body/joint creators with world = 0 --> not inserted into any
534world. allow bodies/joints to be detached from a world (this is what happens
535to grouped joints when a world is destroyed).
536 can bodies and joints be linked together when not attached to world??
537 what happens when we have an island of b/j, some of which are not in
538 world? soln: dont keep lists of b/j in the world, just infer it from
539 the islands?
540
541body & joint disabling / enabling
542
543start a change log.
544
545collision flags - 0xffff mask.
546
547dBodyGetFiniteRotationMode() / ...Axis()
548
549dBodyAddForceAtRelPos()
550
551ball & socket joint limits and motors.
552
553auto-build env on windows: 3 compilers, debug/release, short/double =
55412 combinations --> auto logs.
555
556handle infinities better: HUGE_VALF is not commanly defined, it seems.
557get rid of the __USE_ISOC9X macro in common.h
558perhaps just use a "big" number instead of the actual IEEE infinity, it's
559more portable anyway.
560 --> new config system
561
562dCloseODE() - tidy up *all* allocated memory, esp in geom.cpp. used to keep
563leak detectors happy.
564
565extra API to get lambda and J'*lambda from last timestep.
566
567better stack implementation that is not so system dependent. but how will
568we do dynamic page allocation? do we even need to?
569
570
571all collision files will now be collision_*, not geom_*
572
573check exported global symbols - no C++ mangling.
574
575rename dSphere etc to dxSphere etc.
576
577C interface support for making new classes.
578
579make sure DLL-ized stuff preserved ... but class numbers should no longer be
580exported.
581
582point geom ( = sphere of radius 0 )
583
584geoms stored in doubly linked lists in space (fast removal).
585
586bodies need to keep geoms pointers and call dGeomMoved() in dBodySetPosition()
587etc and world step. PROBLEM: links dynamics and collision together too much,
588makes it hard to extract ODE collision ... unless we say: dGeomMoved() and
589dGeomID must be supplied by the new collision library!
590
591dCollide() should take spaces as arguments - it should call dSpaceCollide2()
592with its own callback that puts all found contacts in the array, stopping
593when there is no more space left in the array.
594
595dxSpace::getGeom() - the geom numbers will change as geoms are dirtied - find
596some other numbering scheme, or document this behavior.
597
598the 'placeable' property - objects that should not ever be attached to bodies
599should flag an error when setBody etc are called.
600
601dGeomSetBody(0) - DOC: the position and orientation of the body will be
602preserved. in this case the geom should NOT be dirtied (dGeomMoved() should
603not be called).
604
605DOC: dGeomGetBodyNext() as part of dynamics/collision interface
606
607groups/spaces are subclasses of geom.
608
609groups/spaces can contain other groups/spaces. geom can be owned by a
610group/space. collision handling:
611 geom-geom : standard collision function
612 geom-group : special space code
613 group-group : n^2 tests (or n space tests) - hard to optimize because
614 of disjoint space representations.
615 group internal : normal space internal-collision code
616
617groups/spaces can be told that some objects never move, i.e. that the objects
618are locked. should we lock the whole space?
619 locking: the AABB for the object is not recalculated
620
621groups/spaces can be told that the internal contents self-intersect or not.
622actually an old ODE group is the equivalent of an old ODE simple space.
623 - just call dCollide() or not.
624
625the group doesn't get passed to the space callback any more ... only the
626intersecting geoms get passed? maybe the callback can initiate the extra
627intersection tests itself? (because we want programmable flexibility to
628determine what gets intersected and what doesn't)
629 - NO
630
631infrastructure to indicate when an object has moved (and thus its AABB needs
632to be recalculated)
633
634space enumeration functions. make sure that there are no additions or deletions
635while enumeration is taking place.
636 - documented the behavior, didn't disallow it
637
638cache the AABB in the dxGeom? (for non-moving objects) - perhaps keep a
639pointer to separately allocated space? ... no
640
641DOC: dGeomGetClass() is a first-class geom function, not in the "User
642defined classes" section. it returns a constant that can be checked
643against dSphereClass etc.
644
645remove dxGeom dependence on dBodyID? ... not yet
646
647dBase -> dxBase
648
649allow a geom to be inserted into multiple spaces? need this to optimize some
650kinds of tests ... no
651
652update docs.
653
654make CHECK_NOT_LOCKED an assert.
655
656DOC: "Calling these functions on a non-placeable geom results in a
657runtime error." ...in the debug build only?
658
659non-placeable geoms should not allocate dxPosR. perhaps pass a dGeom
660constructor arg that says 'placeable' or not - this also sets the
661GEOM_PLACEABLE flag.
662
663GeomTransform:
664 final_pos and final_R valid if no GEOM_AABB_BAD flag!!!
665 fix up this code, esp use of ComputeTX().
666
667Space incompatibilities: no dSpaceDestroy(), dGeomDestroy() does not
668take a dSpaceID ... dSpaceDestroy() added.
669
670GeomGroup incompatibilities:
671 dCollide() used to take a GeomGroup and would return all the contact
672 points for all the intersecting objects. now you have to call
673 dSpaceCollide2() and get a callback for each one.
674 need to provide old behavior.
675
676simple space optimization: we should keep the precomputed AABB for the
677non-moving geoms around, so that when the other geoms move we can just
678compute the AABBs for those geoms and then combine it with the non-moving AABB.
679 --> too hard!
680
681collision build options: old and new
682
683tidyups for collision:
684 * rationalize what stuff goes in what source files, and file names
685 * minimize set of header files that all collision* sources use - after
686 all changes.
687 * update ode-cpp stuff (C++ interface header files).
688
689porting guide:
690 ODE list email
691
692 dGeomGetSpaceAABB() deleted
693
694 dGeomGetClass (geom_group); used to return a unique type for
695 GeomGroups, but now it returns dSimpleSpaceID.
696
697tidyups: update DLL declarations.
698
diff --git a/libraries/ode-0.9/ode/demo/Makefile.am b/libraries/ode-0.9/ode/demo/Makefile.am
deleted file mode 100644
index 361ad53..0000000
--- a/libraries/ode-0.9/ode/demo/Makefile.am
+++ /dev/null
@@ -1,254 +0,0 @@
1AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
2AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
3
4noinst_PROGRAMS=demo_collision \
5 demo_slider \
6 demo_feedback \
7 demo_crash \
8 demo_space \
9 demo_I \
10 demo_friction \
11 demo_space_stress \
12 demo_boxstack demo_hinge \
13 demo_step \
14 demo_buggy \
15 demo_joints \
16 demo_motor \
17 demo_chain1 \
18 demo_chain2 \
19 demo_cylvssphere \
20 demo_ode \
21 demo_plane2d \
22 demo_heightfield \
23 demo_convex_cd \
24 demo_jointPR
25if TRIMESH
26noinst_PROGRAMS+= demo_trimesh demo_moving_trimesh demo_basket demo_cyl
27endif
28demo_collision_SOURCES= demo_collision.cpp
29demo_slider_SOURCES= demo_slider.cpp
30demo_feedback_SOURCES= demo_feedback.cpp
31demo_crash_SOURCES= demo_crash.cpp
32demo_space_SOURCES= demo_space.cpp
33demo_I_SOURCES= demo_I.cpp
34demo_friction_SOURCES= demo_friction.cpp
35demo_space_stress_SOURCES= demo_space_stress.cpp
36demo_boxstack_SOURCES= demo_boxstack.cpp
37demo_hinge_SOURCES= demo_hinge.cpp
38demo_step_SOURCES= demo_step.cpp
39demo_buggy_SOURCES= demo_buggy.cpp
40demo_cyl_SOURCES= demo_cyl.cpp world_geom3.h
41demo_cylvssphere_SOURCES= demo_cylvssphere.cpp
42demo_joints_SOURCES= demo_joints.cpp
43demo_jointPR_SOURCES= demo_jointPR.cpp
44demo_motor_SOURCES= demo_motor.cpp
45demo_chain1_SOURCES= demo_chain1.c
46demo_chain2_SOURCES= demo_chain2.cpp
47demo_ode_SOURCES= demo_ode.cpp
48demo_plane2d_SOURCES= demo_plane2d.cpp
49demo_heightfield_SOURCES= demo_heightfield.cpp
50demo_convex_cd_SOURCES= demo_convex_cd.cpp
51demo_collision_LDFLAGS= -L$(top_builddir)/drawstuff/src \
52 -L$(top_builddir)/ode/src @LDFLAGS@
53demo_slider_LDFLAGS= -L$(top_builddir)/drawstuff/src \
54 -L$(top_builddir)/ode/src @LDFLAGS@
55demo_feedback_LDFLAGS= -L$(top_builddir)/drawstuff/src \
56 -L$(top_builddir)/ode/src @LDFLAGS@
57demo_crash_LDFLAGS= -L$(top_builddir)/drawstuff/src \
58 -L$(top_builddir)/ode/src @LDFLAGS@
59demo_space_LDFLAGS= -L$(top_builddir)/drawstuff/src \
60 -L$(top_builddir)/ode/src @LDFLAGS@
61demo_I_LDFLAGS= -L$(top_builddir)/drawstuff/src \
62 -L$(top_builddir)/ode/src @LDFLAGS@
63demo_friction_LDFLAGS= -L$(top_builddir)/drawstuff/src \
64 -L$(top_builddir)/ode/src @LDFLAGS@
65demo_space_stress_LDFLAGS= -L$(top_builddir)/drawstuff/src \
66 -L$(top_builddir)/ode/src @LDFLAGS@
67demo_boxstack_LDFLAGS= -L$(top_builddir)/drawstuff/src \
68 -L$(top_builddir)/ode/src @LDFLAGS@
69demo_hinge_LDFLAGS= -L$(top_builddir)/drawstuff/src \
70 -L$(top_builddir)/ode/src @LDFLAGS@
71demo_step_LDFLAGS= -L$(top_builddir)/drawstuff/src \
72 -L$(top_builddir)/ode/src @LDFLAGS@
73demo_buggy_LDFLAGS= -L$(top_builddir)/drawstuff/src \
74 -L$(top_builddir)/ode/src @LDFLAGS@
75demo_cyl_LDFLAGS= -L$(top_builddir)/drawstuff/src \
76 -L$(top_builddir)/ode/src @LDFLAGS@
77demo_cylvssphere_LDFLAGS= -L$(top_builddir)/drawstuff/src \
78 -L$(top_builddir)/ode/src @LDFLAGS@
79demo_joints_LDFLAGS= -L$(top_builddir)/drawstuff/src \
80 -L$(top_builddir)/ode/src @LDFLAGS@
81demo_jointPR_LDFLAGS= -L$(top_builddir)/drawstuff/src \
82 -L$(top_builddir)/ode/src @LDFLAGS@
83demo_motor_LDFLAGS= -L$(top_builddir)/drawstuff/src \
84 -L$(top_builddir)/ode/src @LDFLAGS@
85demo_chain1_LDFLAGS= -L$(top_builddir)/drawstuff/src \
86 -L$(top_builddir)/ode/src @LDFLAGS@
87demo_chain2_LDFLAGS= -L$(top_builddir)/drawstuff/src \
88 -L$(top_builddir)/ode/src @LDFLAGS@
89demo_ode_LDFLAGS= -L$(top_builddir)/drawstuff/src \
90 -L$(top_builddir)/ode/src @LDFLAGS@
91demo_plane2d_LDFLAGS= -L$(top_builddir)/drawstuff/src \
92 -L$(top_builddir)/ode/src @LDFLAGS@
93demo_heightfield_LDFLAGS= -L$(top_builddir)/drawstuff/src \
94 -L$(top_builddir)/ode/src @LDFLAGS@
95demo_convex_cd_LDFLAGS= -L$(top_builddir)/drawstuff/src \
96 -L$(top_builddir)/ode/src @LDFLAGS@
97
98demo_collision_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
99 $(top_builddir)/drawstuff/src/libdrawstuff.a
100demo_slider_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
101 $(top_builddir)/drawstuff/src/libdrawstuff.a
102demo_feedback_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
103 $(top_builddir)/drawstuff/src/libdrawstuff.a
104demo_crash_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
105 $(top_builddir)/drawstuff/src/libdrawstuff.a
106demo_space_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
107 $(top_builddir)/drawstuff/src/libdrawstuff.a
108demo_I_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
109 $(top_builddir)/drawstuff/src/libdrawstuff.a
110demo_friction_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
111 $(top_builddir)/drawstuff/src/libdrawstuff.a
112demo_space_stress_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
113 $(top_builddir)/drawstuff/src/libdrawstuff.a
114demo_boxstack_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
115 $(top_builddir)/drawstuff/src/libdrawstuff.a
116demo_hinge_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
117 $(top_builddir)/drawstuff/src/libdrawstuff.a
118demo_step_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
119 $(top_builddir)/drawstuff/src/libdrawstuff.a
120demo_buggy_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
121 $(top_builddir)/drawstuff/src/libdrawstuff.a
122demo_cyl_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
123 $(top_builddir)/drawstuff/src/libdrawstuff.a
124demo_cylvssphere_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
125 $(top_builddir)/drawstuff/src/libdrawstuff.a
126demo_joints_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
127 $(top_builddir)/drawstuff/src/libdrawstuff.a
128demo_jointPR_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
129 $(top_builddir)/drawstuff/src/libdrawstuff.a
130demo_motor_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
131 $(top_builddir)/drawstuff/src/libdrawstuff.a
132demo_chain1_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
133 $(top_builddir)/drawstuff/src/libdrawstuff.a
134demo_chain2_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
135 $(top_builddir)/drawstuff/src/libdrawstuff.a
136demo_ode_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
137 $(top_builddir)/drawstuff/src/libdrawstuff.a
138demo_plane2d_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
139 $(top_builddir)/drawstuff/src/libdrawstuff.a
140demo_heightfield_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
141 $(top_builddir)/drawstuff/src/libdrawstuff.a
142demo_convex_cd_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
143 $(top_builddir)/drawstuff/src/libdrawstuff.a
144
145if TRIMESH
146demo_trimesh_SOURCES= demo_trimesh.cpp
147demo_moving_trimesh_SOURCES= demo_moving_trimesh.cpp
148demo_basket_SOURCES= demo_basket.cpp
149demo_trimesh_LDFLAGS= -L$(top_builddir)/drawstuff/src \
150 -L$(top_builddir)/ode/src @LDFLAGS@ \
151 @GL_LIBS@ @LIBS@
152demo_moving_trimesh_LDFLAGS= -L$(top_builddir)/drawstuff/src \
153 -L$(top_builddir)/ode/src @LDFLAGS@ \
154 @GL_LIBS@ @LIBS@
155demo_basket_LDFLAGS= -L$(top_builddir)/drawstuff/src \
156 -L$(top_builddir)/ode/src @LDFLAGS@ \
157 @GL_LIBS@ @LIBS@
158demo_trimesh_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
159 $(top_builddir)/drawstuff/src/libdrawstuff.a
160demo_moving_trimesh_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
161 $(top_builddir)/drawstuff/src/libdrawstuff.a
162
163demo_basket_DEPENDENCIES= $(top_builddir)/ode/src/libode.a \
164 $(top_builddir)/drawstuff/src/libdrawstuff.a
165
166endif
167
168demo_ode_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
169demo_plane2d_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
170demo_heightfield_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
171demo_chain2_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
172demo_chain1_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
173demo_joints_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
174demo_jointPR_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
175demo_motor_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
176demo_buggy_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
177demo_cyl_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
178demo_cylvssphere_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
179demo_step_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
180demo_hinge_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
181demo_boxstack_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
182demo_space_stress_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
183demo_friction_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
184demo_I_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
185demo_space_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
186demo_crash_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
187demo_slider_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
188demo_feedback_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
189demo_collision_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
190demo_convex_cd_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
191
192
193if TRIMESH
194demo_trimesh_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
195demo_moving_trimesh_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
196demo_basket_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
197endif
198
199
200if WIN32
201resources.o: ../../drawstuff/src/resources.rc ../../drawstuff/src/resource.h
202 @WINDRES@ ../../drawstuff/src/resources.rc -o resources.o
203demo_ode_LDADD+= resources.o
204demo_heightfield_LDADD+= resources.o
205demo_chain2_LDADD+= resources.o
206demo_chain1_LDADD+= resources.o
207demo_joints_LDADD+= resources.o
208demo_jointPR_LDADD+= resources.o
209demo_motor_LDADD+= resources.o
210demo_buggy_LDADD+= resources.o
211demo_cyl_LDADD+= resources.o
212demo_cylvssphere_LDADD+= resources.o
213demo_step_LDADD+= resources.o
214demo_hinge_LDADD+= resources.o
215demo_boxstack_LDADD+= resources.o
216demo_space_stress_LDADD+= resources.o
217demo_friction_LDADD+= resources.o
218demo_I_LDADD+= resources.o
219demo_space_LDADD+= resources.o
220demo_crash_LDADD+= resources.o
221demo_slider_LDADD+= resources.o
222demo_feedback_LDADD+= resources.o
223demo_collision_LDADD+= resources.o
224demo_convex_cd_LDADD+= resources.o
225demo_ode_DEPENDENCIES+= resources.o
226demo_chain2_DEPENDENCIES+= resources.o
227demo_chain1_DEPENDENCIES+= resources.o
228demo_joints_DEPENDENCIES+= resources.o
229demo_jointPR_DEPENDENCIES+= resources.o
230demo_motor_DEPENDENCIES+= resources.o
231demo_buggy_DEPENDENCIES+= resources.o
232demo_cyl_DEPENDENCIES+= resources.o
233demo_cylvssphere_DEPENDENCIES+= resources.o
234demo_step_DEPENDENCIES+= resources.o
235demo_hinge_DEPENDENCIES+= resources.o
236demo_boxstack_DEPENDENCIES+= resources.o
237demo_space_stress_DEPENDENCIES+= resources.o
238demo_friction_DEPENDENCIES+= resources.o
239demo_I_DEPENDENCIES+= resources.o
240demo_space_DEPENDENCIES+= resources.o
241demo_crash_DEPENDENCIES+= resources.o
242demo_slider_DEPENDENCIES+= resources.o
243demo_feedback_DEPENDENCIES+= resources.o
244demo_collision_DEPENDENCIES+= resources.o
245demo_convex_cd_DEPENDENCIES+= resources.o
246
247if TRIMESH
248demo_trimesh_LDADD+= resources.o
249demo_moving_trimesh_LDADD+= resources.o
250demo_trimesh_DEPENDENCIES+= resources.o
251demo_moving_trimesh_DEPENDENCIES+= resources.o
252demo_basket_DEPENDENCIES+= resources.o
253endif
254endif
diff --git a/libraries/ode-0.9/ode/demo/Makefile.in b/libraries/ode-0.9/ode/demo/Makefile.in
deleted file mode 100644
index 8e73f18..0000000
--- a/libraries/ode-0.9/ode/demo/Makefile.in
+++ /dev/null
@@ -1,953 +0,0 @@
1# Makefile.in generated by automake 1.10 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
6# This Makefile.in is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13# PARTICULAR PURPOSE.
14
15@SET_MAKE@
16
17VPATH = @srcdir@
18pkgdatadir = $(datadir)/@PACKAGE@
19pkglibdir = $(libdir)/@PACKAGE@
20pkgincludedir = $(includedir)/@PACKAGE@
21am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
22install_sh_DATA = $(install_sh) -c -m 644
23install_sh_PROGRAM = $(install_sh) -c
24install_sh_SCRIPT = $(install_sh) -c
25INSTALL_HEADER = $(INSTALL_DATA)
26transform = $(program_transform_name)
27NORMAL_INSTALL = :
28PRE_INSTALL = :
29POST_INSTALL = :
30NORMAL_UNINSTALL = :
31PRE_UNINSTALL = :
32POST_UNINSTALL = :
33build_triplet = @build@
34host_triplet = @host@
35target_triplet = @target@
36noinst_PROGRAMS = demo_collision$(EXEEXT) demo_slider$(EXEEXT) \
37 demo_feedback$(EXEEXT) demo_crash$(EXEEXT) demo_space$(EXEEXT) \
38 demo_I$(EXEEXT) demo_friction$(EXEEXT) \
39 demo_space_stress$(EXEEXT) demo_boxstack$(EXEEXT) \
40 demo_hinge$(EXEEXT) demo_step$(EXEEXT) demo_buggy$(EXEEXT) \
41 demo_joints$(EXEEXT) demo_motor$(EXEEXT) demo_chain1$(EXEEXT) \
42 demo_chain2$(EXEEXT) demo_cylvssphere$(EXEEXT) \
43 demo_ode$(EXEEXT) demo_plane2d$(EXEEXT) \
44 demo_heightfield$(EXEEXT) demo_convex_cd$(EXEEXT) \
45 demo_jointPR$(EXEEXT) $(am__EXEEXT_1)
46@TRIMESH_TRUE@am__append_1 = demo_trimesh demo_moving_trimesh demo_basket demo_cyl
47@WIN32_TRUE@am__append_2 = resources.o
48@WIN32_TRUE@am__append_3 = resources.o
49@WIN32_TRUE@am__append_4 = resources.o
50@WIN32_TRUE@am__append_5 = resources.o
51@WIN32_TRUE@am__append_6 = resources.o
52@WIN32_TRUE@am__append_7 = resources.o
53@WIN32_TRUE@am__append_8 = resources.o
54@WIN32_TRUE@am__append_9 = resources.o
55@WIN32_TRUE@am__append_10 = resources.o
56@WIN32_TRUE@am__append_11 = resources.o
57@WIN32_TRUE@am__append_12 = resources.o
58@WIN32_TRUE@am__append_13 = resources.o
59@WIN32_TRUE@am__append_14 = resources.o
60@WIN32_TRUE@am__append_15 = resources.o
61@WIN32_TRUE@am__append_16 = resources.o
62@WIN32_TRUE@am__append_17 = resources.o
63@WIN32_TRUE@am__append_18 = resources.o
64@WIN32_TRUE@am__append_19 = resources.o
65@WIN32_TRUE@am__append_20 = resources.o
66@WIN32_TRUE@am__append_21 = resources.o
67@WIN32_TRUE@am__append_22 = resources.o
68@WIN32_TRUE@am__append_23 = resources.o
69@WIN32_TRUE@am__append_24 = resources.o
70@WIN32_TRUE@am__append_25 = resources.o
71@WIN32_TRUE@am__append_26 = resources.o
72@WIN32_TRUE@am__append_27 = resources.o
73@WIN32_TRUE@am__append_28 = resources.o
74@WIN32_TRUE@am__append_29 = resources.o
75@WIN32_TRUE@am__append_30 = resources.o
76@WIN32_TRUE@am__append_31 = resources.o
77@WIN32_TRUE@am__append_32 = resources.o
78@WIN32_TRUE@am__append_33 = resources.o
79@WIN32_TRUE@am__append_34 = resources.o
80@WIN32_TRUE@am__append_35 = resources.o
81@WIN32_TRUE@am__append_36 = resources.o
82@WIN32_TRUE@am__append_37 = resources.o
83@WIN32_TRUE@am__append_38 = resources.o
84@WIN32_TRUE@am__append_39 = resources.o
85@WIN32_TRUE@am__append_40 = resources.o
86@WIN32_TRUE@am__append_41 = resources.o
87@WIN32_TRUE@am__append_42 = resources.o
88@WIN32_TRUE@am__append_43 = resources.o
89@WIN32_TRUE@am__append_44 = resources.o
90@TRIMESH_TRUE@@WIN32_TRUE@am__append_45 = resources.o
91@TRIMESH_TRUE@@WIN32_TRUE@am__append_46 = resources.o
92@TRIMESH_TRUE@@WIN32_TRUE@am__append_47 = resources.o
93@TRIMESH_TRUE@@WIN32_TRUE@am__append_48 = resources.o
94@TRIMESH_TRUE@@WIN32_TRUE@am__append_49 = resources.o
95subdir = ode/demo
96DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
97ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
98am__aclocal_m4_deps = $(top_srcdir)/configure.in
99am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
100 $(ACLOCAL_M4)
101mkinstalldirs = $(install_sh) -d
102CONFIG_HEADER = $(top_builddir)/include/ode/config.h
103CONFIG_CLEAN_FILES =
104@TRIMESH_TRUE@am__EXEEXT_1 = demo_trimesh$(EXEEXT) \
105@TRIMESH_TRUE@ demo_moving_trimesh$(EXEEXT) \
106@TRIMESH_TRUE@ demo_basket$(EXEEXT) demo_cyl$(EXEEXT)
107PROGRAMS = $(noinst_PROGRAMS)
108am_demo_I_OBJECTS = demo_I.$(OBJEXT)
109demo_I_OBJECTS = $(am_demo_I_OBJECTS)
110demo_I_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(demo_I_LDFLAGS) \
111 $(LDFLAGS) -o $@
112am__demo_basket_SOURCES_DIST = demo_basket.cpp
113@TRIMESH_TRUE@am_demo_basket_OBJECTS = demo_basket.$(OBJEXT)
114demo_basket_OBJECTS = $(am_demo_basket_OBJECTS)
115demo_basket_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
116 $(demo_basket_LDFLAGS) $(LDFLAGS) -o $@
117am_demo_boxstack_OBJECTS = demo_boxstack.$(OBJEXT)
118demo_boxstack_OBJECTS = $(am_demo_boxstack_OBJECTS)
119demo_boxstack_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
120 $(demo_boxstack_LDFLAGS) $(LDFLAGS) -o $@
121am_demo_buggy_OBJECTS = demo_buggy.$(OBJEXT)
122demo_buggy_OBJECTS = $(am_demo_buggy_OBJECTS)
123demo_buggy_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
124 $(demo_buggy_LDFLAGS) $(LDFLAGS) -o $@
125am_demo_chain1_OBJECTS = demo_chain1.$(OBJEXT)
126demo_chain1_OBJECTS = $(am_demo_chain1_OBJECTS)
127demo_chain1_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
128 $(demo_chain1_LDFLAGS) $(LDFLAGS) -o $@
129am_demo_chain2_OBJECTS = demo_chain2.$(OBJEXT)
130demo_chain2_OBJECTS = $(am_demo_chain2_OBJECTS)
131demo_chain2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
132 $(demo_chain2_LDFLAGS) $(LDFLAGS) -o $@
133am_demo_collision_OBJECTS = demo_collision.$(OBJEXT)
134demo_collision_OBJECTS = $(am_demo_collision_OBJECTS)
135demo_collision_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
136 $(demo_collision_LDFLAGS) $(LDFLAGS) -o $@
137am_demo_convex_cd_OBJECTS = demo_convex_cd.$(OBJEXT)
138demo_convex_cd_OBJECTS = $(am_demo_convex_cd_OBJECTS)
139demo_convex_cd_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
140 $(demo_convex_cd_LDFLAGS) $(LDFLAGS) -o $@
141am_demo_crash_OBJECTS = demo_crash.$(OBJEXT)
142demo_crash_OBJECTS = $(am_demo_crash_OBJECTS)
143demo_crash_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
144 $(demo_crash_LDFLAGS) $(LDFLAGS) -o $@
145am_demo_cyl_OBJECTS = demo_cyl.$(OBJEXT)
146demo_cyl_OBJECTS = $(am_demo_cyl_OBJECTS)
147demo_cyl_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
148 $(demo_cyl_LDFLAGS) $(LDFLAGS) -o $@
149am_demo_cylvssphere_OBJECTS = demo_cylvssphere.$(OBJEXT)
150demo_cylvssphere_OBJECTS = $(am_demo_cylvssphere_OBJECTS)
151demo_cylvssphere_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
152 $(demo_cylvssphere_LDFLAGS) $(LDFLAGS) -o $@
153am_demo_feedback_OBJECTS = demo_feedback.$(OBJEXT)
154demo_feedback_OBJECTS = $(am_demo_feedback_OBJECTS)
155demo_feedback_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
156 $(demo_feedback_LDFLAGS) $(LDFLAGS) -o $@
157am_demo_friction_OBJECTS = demo_friction.$(OBJEXT)
158demo_friction_OBJECTS = $(am_demo_friction_OBJECTS)
159demo_friction_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
160 $(demo_friction_LDFLAGS) $(LDFLAGS) -o $@
161am_demo_heightfield_OBJECTS = demo_heightfield.$(OBJEXT)
162demo_heightfield_OBJECTS = $(am_demo_heightfield_OBJECTS)
163demo_heightfield_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
164 $(demo_heightfield_LDFLAGS) $(LDFLAGS) -o $@
165am_demo_hinge_OBJECTS = demo_hinge.$(OBJEXT)
166demo_hinge_OBJECTS = $(am_demo_hinge_OBJECTS)
167demo_hinge_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
168 $(demo_hinge_LDFLAGS) $(LDFLAGS) -o $@
169am_demo_jointPR_OBJECTS = demo_jointPR.$(OBJEXT)
170demo_jointPR_OBJECTS = $(am_demo_jointPR_OBJECTS)
171demo_jointPR_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
172 $(demo_jointPR_LDFLAGS) $(LDFLAGS) -o $@
173am_demo_joints_OBJECTS = demo_joints.$(OBJEXT)
174demo_joints_OBJECTS = $(am_demo_joints_OBJECTS)
175demo_joints_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
176 $(demo_joints_LDFLAGS) $(LDFLAGS) -o $@
177am_demo_motor_OBJECTS = demo_motor.$(OBJEXT)
178demo_motor_OBJECTS = $(am_demo_motor_OBJECTS)
179demo_motor_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
180 $(demo_motor_LDFLAGS) $(LDFLAGS) -o $@
181am__demo_moving_trimesh_SOURCES_DIST = demo_moving_trimesh.cpp
182@TRIMESH_TRUE@am_demo_moving_trimesh_OBJECTS = \
183@TRIMESH_TRUE@ demo_moving_trimesh.$(OBJEXT)
184demo_moving_trimesh_OBJECTS = $(am_demo_moving_trimesh_OBJECTS)
185demo_moving_trimesh_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
186 $(demo_moving_trimesh_LDFLAGS) $(LDFLAGS) -o $@
187am_demo_ode_OBJECTS = demo_ode.$(OBJEXT)
188demo_ode_OBJECTS = $(am_demo_ode_OBJECTS)
189demo_ode_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
190 $(demo_ode_LDFLAGS) $(LDFLAGS) -o $@
191am_demo_plane2d_OBJECTS = demo_plane2d.$(OBJEXT)
192demo_plane2d_OBJECTS = $(am_demo_plane2d_OBJECTS)
193demo_plane2d_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
194 $(demo_plane2d_LDFLAGS) $(LDFLAGS) -o $@
195am_demo_slider_OBJECTS = demo_slider.$(OBJEXT)
196demo_slider_OBJECTS = $(am_demo_slider_OBJECTS)
197demo_slider_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
198 $(demo_slider_LDFLAGS) $(LDFLAGS) -o $@
199am_demo_space_OBJECTS = demo_space.$(OBJEXT)
200demo_space_OBJECTS = $(am_demo_space_OBJECTS)
201demo_space_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
202 $(demo_space_LDFLAGS) $(LDFLAGS) -o $@
203am_demo_space_stress_OBJECTS = demo_space_stress.$(OBJEXT)
204demo_space_stress_OBJECTS = $(am_demo_space_stress_OBJECTS)
205demo_space_stress_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
206 $(demo_space_stress_LDFLAGS) $(LDFLAGS) -o $@
207am_demo_step_OBJECTS = demo_step.$(OBJEXT)
208demo_step_OBJECTS = $(am_demo_step_OBJECTS)
209demo_step_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
210 $(demo_step_LDFLAGS) $(LDFLAGS) -o $@
211am__demo_trimesh_SOURCES_DIST = demo_trimesh.cpp
212@TRIMESH_TRUE@am_demo_trimesh_OBJECTS = demo_trimesh.$(OBJEXT)
213demo_trimesh_OBJECTS = $(am_demo_trimesh_OBJECTS)
214demo_trimesh_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
215 $(demo_trimesh_LDFLAGS) $(LDFLAGS) -o $@
216DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
217depcomp = $(SHELL) $(top_srcdir)/depcomp
218am__depfiles_maybe = depfiles
219COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
220 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
221CCLD = $(CC)
222LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
223CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
224 $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
225CXXLD = $(CXX)
226CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
227 -o $@
228SOURCES = $(demo_I_SOURCES) $(demo_basket_SOURCES) \
229 $(demo_boxstack_SOURCES) $(demo_buggy_SOURCES) \
230 $(demo_chain1_SOURCES) $(demo_chain2_SOURCES) \
231 $(demo_collision_SOURCES) $(demo_convex_cd_SOURCES) \
232 $(demo_crash_SOURCES) $(demo_cyl_SOURCES) \
233 $(demo_cylvssphere_SOURCES) $(demo_feedback_SOURCES) \
234 $(demo_friction_SOURCES) $(demo_heightfield_SOURCES) \
235 $(demo_hinge_SOURCES) $(demo_jointPR_SOURCES) \
236 $(demo_joints_SOURCES) $(demo_motor_SOURCES) \
237 $(demo_moving_trimesh_SOURCES) $(demo_ode_SOURCES) \
238 $(demo_plane2d_SOURCES) $(demo_slider_SOURCES) \
239 $(demo_space_SOURCES) $(demo_space_stress_SOURCES) \
240 $(demo_step_SOURCES) $(demo_trimesh_SOURCES)
241DIST_SOURCES = $(demo_I_SOURCES) $(am__demo_basket_SOURCES_DIST) \
242 $(demo_boxstack_SOURCES) $(demo_buggy_SOURCES) \
243 $(demo_chain1_SOURCES) $(demo_chain2_SOURCES) \
244 $(demo_collision_SOURCES) $(demo_convex_cd_SOURCES) \
245 $(demo_crash_SOURCES) $(demo_cyl_SOURCES) \
246 $(demo_cylvssphere_SOURCES) $(demo_feedback_SOURCES) \
247 $(demo_friction_SOURCES) $(demo_heightfield_SOURCES) \
248 $(demo_hinge_SOURCES) $(demo_jointPR_SOURCES) \
249 $(demo_joints_SOURCES) $(demo_motor_SOURCES) \
250 $(am__demo_moving_trimesh_SOURCES_DIST) $(demo_ode_SOURCES) \
251 $(demo_plane2d_SOURCES) $(demo_slider_SOURCES) \
252 $(demo_space_SOURCES) $(demo_space_stress_SOURCES) \
253 $(demo_step_SOURCES) $(am__demo_trimesh_SOURCES_DIST)
254ETAGS = etags
255CTAGS = ctags
256DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
257ACLOCAL = @ACLOCAL@
258ALLOCA = @ALLOCA@
259AMTAR = @AMTAR@
260ARCHFLAGS = @ARCHFLAGS@
261AUTOCONF = @AUTOCONF@
262AUTOHEADER = @AUTOHEADER@
263AUTOMAKE = @AUTOMAKE@
264AWK = @AWK@
265CC = @CC@
266CCDEPMODE = @CCDEPMODE@
267CFLAGS = @CFLAGS@
268CPP = @CPP@
269CPPFLAGS = @CPPFLAGS@
270CXX = @CXX@
271CXXDEPMODE = @CXXDEPMODE@
272CXXFLAGS = @CXXFLAGS@
273CYGPATH_W = @CYGPATH_W@
274DEFS = @DEFS@
275DEPDIR = @DEPDIR@
276DRAWSTUFF = @DRAWSTUFF@
277ECHO_C = @ECHO_C@
278ECHO_N = @ECHO_N@
279ECHO_T = @ECHO_T@
280EGREP = @EGREP@
281EXEEXT = @EXEEXT@
282GL_LIBS = @GL_LIBS@
283GREP = @GREP@
284INSTALL = @INSTALL@
285INSTALL_DATA = @INSTALL_DATA@
286INSTALL_PROGRAM = @INSTALL_PROGRAM@
287INSTALL_SCRIPT = @INSTALL_SCRIPT@
288INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
289LDFLAGS = @LDFLAGS@
290LIBOBJS = @LIBOBJS@
291LIBS = @LIBS@
292LTLIBOBJS = @LTLIBOBJS@
293MAKEINFO = @MAKEINFO@
294MKDIR_P = @MKDIR_P@
295OBJEXT = @OBJEXT@
296ODE_AGE = @ODE_AGE@
297ODE_CURRENT = @ODE_CURRENT@
298ODE_RELEASE = @ODE_RELEASE@
299ODE_REVISION = @ODE_REVISION@
300ODE_SONAME = @ODE_SONAME@
301PACKAGE = @PACKAGE@
302PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
303PACKAGE_NAME = @PACKAGE_NAME@
304PACKAGE_STRING = @PACKAGE_STRING@
305PACKAGE_TARNAME = @PACKAGE_TARNAME@
306PACKAGE_VERSION = @PACKAGE_VERSION@
307PATH_SEPARATOR = @PATH_SEPARATOR@
308RANLIB = @RANLIB@
309SET_MAKE = @SET_MAKE@
310SHARED_LDFLAGS = @SHARED_LDFLAGS@
311SHELL = @SHELL@
312STRIP = @STRIP@
313TOPDIR = @TOPDIR@
314VERSION = @VERSION@
315WINDRES = @WINDRES@
316XMKMF = @XMKMF@
317X_CFLAGS = @X_CFLAGS@
318X_EXTRA_LIBS = @X_EXTRA_LIBS@
319X_LIBS = @X_LIBS@
320X_PRE_LIBS = @X_PRE_LIBS@
321abs_builddir = @abs_builddir@
322abs_srcdir = @abs_srcdir@
323abs_top_builddir = @abs_top_builddir@
324abs_top_srcdir = @abs_top_srcdir@
325ac_ct_CC = @ac_ct_CC@
326ac_ct_CXX = @ac_ct_CXX@
327ac_ct_WINDRES = @ac_ct_WINDRES@
328am__include = @am__include@
329am__leading_dot = @am__leading_dot@
330am__quote = @am__quote@
331am__tar = @am__tar@
332am__untar = @am__untar@
333bindir = @bindir@
334build = @build@
335build_alias = @build_alias@
336build_cpu = @build_cpu@
337build_os = @build_os@
338build_vendor = @build_vendor@
339builddir = @builddir@
340datadir = @datadir@
341datarootdir = @datarootdir@
342docdir = @docdir@
343dvidir = @dvidir@
344exec_prefix = @exec_prefix@
345host = @host@
346host_alias = @host_alias@
347host_cpu = @host_cpu@
348host_os = @host_os@
349host_vendor = @host_vendor@
350htmldir = @htmldir@
351includedir = @includedir@
352infodir = @infodir@
353install_sh = @install_sh@
354libdir = @libdir@
355libexecdir = @libexecdir@
356localedir = @localedir@
357localstatedir = @localstatedir@
358mandir = @mandir@
359mkdir_p = @mkdir_p@
360oldincludedir = @oldincludedir@
361pdfdir = @pdfdir@
362prefix = @prefix@
363program_transform_name = @program_transform_name@
364psdir = @psdir@
365sbindir = @sbindir@
366sharedstatedir = @sharedstatedir@
367so_ext = @so_ext@
368srcdir = @srcdir@
369sysconfdir = @sysconfdir@
370target = @target@
371target_alias = @target_alias@
372target_cpu = @target_cpu@
373target_os = @target_os@
374target_vendor = @target_vendor@
375top_builddir = @top_builddir@
376top_srcdir = @top_srcdir@
377AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
378AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
379demo_collision_SOURCES = demo_collision.cpp
380demo_slider_SOURCES = demo_slider.cpp
381demo_feedback_SOURCES = demo_feedback.cpp
382demo_crash_SOURCES = demo_crash.cpp
383demo_space_SOURCES = demo_space.cpp
384demo_I_SOURCES = demo_I.cpp
385demo_friction_SOURCES = demo_friction.cpp
386demo_space_stress_SOURCES = demo_space_stress.cpp
387demo_boxstack_SOURCES = demo_boxstack.cpp
388demo_hinge_SOURCES = demo_hinge.cpp
389demo_step_SOURCES = demo_step.cpp
390demo_buggy_SOURCES = demo_buggy.cpp
391demo_cyl_SOURCES = demo_cyl.cpp world_geom3.h
392demo_cylvssphere_SOURCES = demo_cylvssphere.cpp
393demo_joints_SOURCES = demo_joints.cpp
394demo_jointPR_SOURCES = demo_jointPR.cpp
395demo_motor_SOURCES = demo_motor.cpp
396demo_chain1_SOURCES = demo_chain1.c
397demo_chain2_SOURCES = demo_chain2.cpp
398demo_ode_SOURCES = demo_ode.cpp
399demo_plane2d_SOURCES = demo_plane2d.cpp
400demo_heightfield_SOURCES = demo_heightfield.cpp
401demo_convex_cd_SOURCES = demo_convex_cd.cpp
402demo_collision_LDFLAGS = -L$(top_builddir)/drawstuff/src \
403 -L$(top_builddir)/ode/src @LDFLAGS@
404
405demo_slider_LDFLAGS = -L$(top_builddir)/drawstuff/src \
406 -L$(top_builddir)/ode/src @LDFLAGS@
407
408demo_feedback_LDFLAGS = -L$(top_builddir)/drawstuff/src \
409 -L$(top_builddir)/ode/src @LDFLAGS@
410
411demo_crash_LDFLAGS = -L$(top_builddir)/drawstuff/src \
412 -L$(top_builddir)/ode/src @LDFLAGS@
413
414demo_space_LDFLAGS = -L$(top_builddir)/drawstuff/src \
415 -L$(top_builddir)/ode/src @LDFLAGS@
416
417demo_I_LDFLAGS = -L$(top_builddir)/drawstuff/src \
418 -L$(top_builddir)/ode/src @LDFLAGS@
419
420demo_friction_LDFLAGS = -L$(top_builddir)/drawstuff/src \
421 -L$(top_builddir)/ode/src @LDFLAGS@
422
423demo_space_stress_LDFLAGS = -L$(top_builddir)/drawstuff/src \
424 -L$(top_builddir)/ode/src @LDFLAGS@
425
426demo_boxstack_LDFLAGS = -L$(top_builddir)/drawstuff/src \
427 -L$(top_builddir)/ode/src @LDFLAGS@
428
429demo_hinge_LDFLAGS = -L$(top_builddir)/drawstuff/src \
430 -L$(top_builddir)/ode/src @LDFLAGS@
431
432demo_step_LDFLAGS = -L$(top_builddir)/drawstuff/src \
433 -L$(top_builddir)/ode/src @LDFLAGS@
434
435demo_buggy_LDFLAGS = -L$(top_builddir)/drawstuff/src \
436 -L$(top_builddir)/ode/src @LDFLAGS@
437
438demo_cyl_LDFLAGS = -L$(top_builddir)/drawstuff/src \
439 -L$(top_builddir)/ode/src @LDFLAGS@
440
441demo_cylvssphere_LDFLAGS = -L$(top_builddir)/drawstuff/src \
442 -L$(top_builddir)/ode/src @LDFLAGS@
443
444demo_joints_LDFLAGS = -L$(top_builddir)/drawstuff/src \
445 -L$(top_builddir)/ode/src @LDFLAGS@
446
447demo_jointPR_LDFLAGS = -L$(top_builddir)/drawstuff/src \
448 -L$(top_builddir)/ode/src @LDFLAGS@
449
450demo_motor_LDFLAGS = -L$(top_builddir)/drawstuff/src \
451 -L$(top_builddir)/ode/src @LDFLAGS@
452
453demo_chain1_LDFLAGS = -L$(top_builddir)/drawstuff/src \
454 -L$(top_builddir)/ode/src @LDFLAGS@
455
456demo_chain2_LDFLAGS = -L$(top_builddir)/drawstuff/src \
457 -L$(top_builddir)/ode/src @LDFLAGS@
458
459demo_ode_LDFLAGS = -L$(top_builddir)/drawstuff/src \
460 -L$(top_builddir)/ode/src @LDFLAGS@
461
462demo_plane2d_LDFLAGS = -L$(top_builddir)/drawstuff/src \
463 -L$(top_builddir)/ode/src @LDFLAGS@
464
465demo_heightfield_LDFLAGS = -L$(top_builddir)/drawstuff/src \
466 -L$(top_builddir)/ode/src @LDFLAGS@
467
468demo_convex_cd_LDFLAGS = -L$(top_builddir)/drawstuff/src \
469 -L$(top_builddir)/ode/src @LDFLAGS@
470
471demo_collision_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
472 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_43)
473demo_slider_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
474 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_41)
475demo_feedback_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
476 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_42)
477demo_crash_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
478 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_40)
479demo_space_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
480 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_39)
481demo_I_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
482 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_38)
483demo_friction_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
484 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_37)
485demo_space_stress_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
486 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_36)
487demo_boxstack_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
488 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_35)
489demo_hinge_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
490 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_34)
491demo_step_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
492 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_33)
493demo_buggy_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
494 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_30)
495demo_cyl_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
496 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_31)
497demo_cylvssphere_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
498 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_32)
499demo_joints_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
500 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_27)
501demo_jointPR_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
502 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_28)
503demo_motor_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
504 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_29)
505demo_chain1_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
506 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_26)
507demo_chain2_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
508 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_25)
509demo_ode_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
510 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_24)
511demo_plane2d_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
512 $(top_builddir)/drawstuff/src/libdrawstuff.a
513
514demo_heightfield_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
515 $(top_builddir)/drawstuff/src/libdrawstuff.a
516
517demo_convex_cd_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
518 $(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_44)
519@TRIMESH_TRUE@demo_trimesh_SOURCES = demo_trimesh.cpp
520@TRIMESH_TRUE@demo_moving_trimesh_SOURCES = demo_moving_trimesh.cpp
521@TRIMESH_TRUE@demo_basket_SOURCES = demo_basket.cpp
522@TRIMESH_TRUE@demo_trimesh_LDFLAGS = -L$(top_builddir)/drawstuff/src \
523@TRIMESH_TRUE@ -L$(top_builddir)/ode/src @LDFLAGS@ \
524@TRIMESH_TRUE@ @GL_LIBS@ @LIBS@
525
526@TRIMESH_TRUE@demo_moving_trimesh_LDFLAGS = -L$(top_builddir)/drawstuff/src \
527@TRIMESH_TRUE@ -L$(top_builddir)/ode/src @LDFLAGS@ \
528@TRIMESH_TRUE@ @GL_LIBS@ @LIBS@
529
530@TRIMESH_TRUE@demo_basket_LDFLAGS = -L$(top_builddir)/drawstuff/src \
531@TRIMESH_TRUE@ -L$(top_builddir)/ode/src @LDFLAGS@ \
532@TRIMESH_TRUE@ @GL_LIBS@ @LIBS@
533
534@TRIMESH_TRUE@demo_trimesh_DEPENDENCIES = \
535@TRIMESH_TRUE@ $(top_builddir)/ode/src/libode.a \
536@TRIMESH_TRUE@ $(top_builddir)/drawstuff/src/libdrawstuff.a \
537@TRIMESH_TRUE@ $(am__append_47)
538@TRIMESH_TRUE@demo_moving_trimesh_DEPENDENCIES = \
539@TRIMESH_TRUE@ $(top_builddir)/ode/src/libode.a \
540@TRIMESH_TRUE@ $(top_builddir)/drawstuff/src/libdrawstuff.a \
541@TRIMESH_TRUE@ $(am__append_48)
542@TRIMESH_TRUE@demo_basket_DEPENDENCIES = \
543@TRIMESH_TRUE@ $(top_builddir)/ode/src/libode.a \
544@TRIMESH_TRUE@ $(top_builddir)/drawstuff/src/libdrawstuff.a \
545@TRIMESH_TRUE@ $(am__append_49)
546demo_ode_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
547 @GL_LIBS@ @LIBS@ $(am__append_2)
548demo_plane2d_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
549demo_heightfield_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
550 @GL_LIBS@ @LIBS@ $(am__append_3)
551demo_chain2_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
552 @GL_LIBS@ @LIBS@ $(am__append_4)
553demo_chain1_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
554 @GL_LIBS@ @LIBS@ $(am__append_5)
555demo_joints_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
556 @GL_LIBS@ @LIBS@ $(am__append_6)
557demo_jointPR_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
558 @GL_LIBS@ @LIBS@ $(am__append_7)
559demo_motor_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
560 @GL_LIBS@ @LIBS@ $(am__append_8)
561demo_buggy_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
562 @GL_LIBS@ @LIBS@ $(am__append_9)
563demo_cyl_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
564 @GL_LIBS@ @LIBS@ $(am__append_10)
565demo_cylvssphere_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
566 @GL_LIBS@ @LIBS@ $(am__append_11)
567demo_step_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
568 @GL_LIBS@ @LIBS@ $(am__append_12)
569demo_hinge_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
570 @GL_LIBS@ @LIBS@ $(am__append_13)
571demo_boxstack_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
572 @GL_LIBS@ @LIBS@ $(am__append_14)
573demo_space_stress_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
574 @GL_LIBS@ @LIBS@ $(am__append_15)
575demo_friction_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
576 @GL_LIBS@ @LIBS@ $(am__append_16)
577demo_I_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ \
578 @LIBS@ $(am__append_17)
579demo_space_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
580 @GL_LIBS@ @LIBS@ $(am__append_18)
581demo_crash_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
582 @GL_LIBS@ @LIBS@ $(am__append_19)
583demo_slider_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
584 @GL_LIBS@ @LIBS@ $(am__append_20)
585demo_feedback_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
586 @GL_LIBS@ @LIBS@ $(am__append_21)
587demo_collision_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
588 @GL_LIBS@ @LIBS@ $(am__append_22)
589demo_convex_cd_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
590 @GL_LIBS@ @LIBS@ $(am__append_23)
591@TRIMESH_TRUE@demo_trimesh_LDADD = -ldrawstuff \
592@TRIMESH_TRUE@ $(top_builddir)/ode/src/libode.a @GL_LIBS@ \
593@TRIMESH_TRUE@ @LIBS@ $(am__append_45)
594@TRIMESH_TRUE@demo_moving_trimesh_LDADD = -ldrawstuff \
595@TRIMESH_TRUE@ $(top_builddir)/ode/src/libode.a @GL_LIBS@ \
596@TRIMESH_TRUE@ @LIBS@ $(am__append_46)
597@TRIMESH_TRUE@demo_basket_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
598all: all-am
599
600.SUFFIXES:
601.SUFFIXES: .c .cpp .o .obj
602$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
603 @for dep in $?; do \
604 case '$(am__configure_deps)' in \
605 *$$dep*) \
606 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
607 && exit 0; \
608 exit 1;; \
609 esac; \
610 done; \
611 echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/demo/Makefile'; \
612 cd $(top_srcdir) && \
613 $(AUTOMAKE) --foreign ode/demo/Makefile
614.PRECIOUS: Makefile
615Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
616 @case '$?' in \
617 *config.status*) \
618 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
619 *) \
620 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
621 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
622 esac;
623
624$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
625 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
626
627$(top_srcdir)/configure: $(am__configure_deps)
628 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
629$(ACLOCAL_M4): $(am__aclocal_m4_deps)
630 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
631
632clean-noinstPROGRAMS:
633 -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
634demo_I$(EXEEXT): $(demo_I_OBJECTS) $(demo_I_DEPENDENCIES)
635 @rm -f demo_I$(EXEEXT)
636 $(demo_I_LINK) $(demo_I_OBJECTS) $(demo_I_LDADD) $(LIBS)
637demo_basket$(EXEEXT): $(demo_basket_OBJECTS) $(demo_basket_DEPENDENCIES)
638 @rm -f demo_basket$(EXEEXT)
639 $(demo_basket_LINK) $(demo_basket_OBJECTS) $(demo_basket_LDADD) $(LIBS)
640demo_boxstack$(EXEEXT): $(demo_boxstack_OBJECTS) $(demo_boxstack_DEPENDENCIES)
641 @rm -f demo_boxstack$(EXEEXT)
642 $(demo_boxstack_LINK) $(demo_boxstack_OBJECTS) $(demo_boxstack_LDADD) $(LIBS)
643demo_buggy$(EXEEXT): $(demo_buggy_OBJECTS) $(demo_buggy_DEPENDENCIES)
644 @rm -f demo_buggy$(EXEEXT)
645 $(demo_buggy_LINK) $(demo_buggy_OBJECTS) $(demo_buggy_LDADD) $(LIBS)
646demo_chain1$(EXEEXT): $(demo_chain1_OBJECTS) $(demo_chain1_DEPENDENCIES)
647 @rm -f demo_chain1$(EXEEXT)
648 $(demo_chain1_LINK) $(demo_chain1_OBJECTS) $(demo_chain1_LDADD) $(LIBS)
649demo_chain2$(EXEEXT): $(demo_chain2_OBJECTS) $(demo_chain2_DEPENDENCIES)
650 @rm -f demo_chain2$(EXEEXT)
651 $(demo_chain2_LINK) $(demo_chain2_OBJECTS) $(demo_chain2_LDADD) $(LIBS)
652demo_collision$(EXEEXT): $(demo_collision_OBJECTS) $(demo_collision_DEPENDENCIES)
653 @rm -f demo_collision$(EXEEXT)
654 $(demo_collision_LINK) $(demo_collision_OBJECTS) $(demo_collision_LDADD) $(LIBS)
655demo_convex_cd$(EXEEXT): $(demo_convex_cd_OBJECTS) $(demo_convex_cd_DEPENDENCIES)
656 @rm -f demo_convex_cd$(EXEEXT)
657 $(demo_convex_cd_LINK) $(demo_convex_cd_OBJECTS) $(demo_convex_cd_LDADD) $(LIBS)
658demo_crash$(EXEEXT): $(demo_crash_OBJECTS) $(demo_crash_DEPENDENCIES)
659 @rm -f demo_crash$(EXEEXT)
660 $(demo_crash_LINK) $(demo_crash_OBJECTS) $(demo_crash_LDADD) $(LIBS)
661demo_cyl$(EXEEXT): $(demo_cyl_OBJECTS) $(demo_cyl_DEPENDENCIES)
662 @rm -f demo_cyl$(EXEEXT)
663 $(demo_cyl_LINK) $(demo_cyl_OBJECTS) $(demo_cyl_LDADD) $(LIBS)
664demo_cylvssphere$(EXEEXT): $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_DEPENDENCIES)
665 @rm -f demo_cylvssphere$(EXEEXT)
666 $(demo_cylvssphere_LINK) $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_LDADD) $(LIBS)
667demo_feedback$(EXEEXT): $(demo_feedback_OBJECTS) $(demo_feedback_DEPENDENCIES)
668 @rm -f demo_feedback$(EXEEXT)
669 $(demo_feedback_LINK) $(demo_feedback_OBJECTS) $(demo_feedback_LDADD) $(LIBS)
670demo_friction$(EXEEXT): $(demo_friction_OBJECTS) $(demo_friction_DEPENDENCIES)
671 @rm -f demo_friction$(EXEEXT)
672 $(demo_friction_LINK) $(demo_friction_OBJECTS) $(demo_friction_LDADD) $(LIBS)
673demo_heightfield$(EXEEXT): $(demo_heightfield_OBJECTS) $(demo_heightfield_DEPENDENCIES)
674 @rm -f demo_heightfield$(EXEEXT)
675 $(demo_heightfield_LINK) $(demo_heightfield_OBJECTS) $(demo_heightfield_LDADD) $(LIBS)
676demo_hinge$(EXEEXT): $(demo_hinge_OBJECTS) $(demo_hinge_DEPENDENCIES)
677 @rm -f demo_hinge$(EXEEXT)
678 $(demo_hinge_LINK) $(demo_hinge_OBJECTS) $(demo_hinge_LDADD) $(LIBS)
679demo_jointPR$(EXEEXT): $(demo_jointPR_OBJECTS) $(demo_jointPR_DEPENDENCIES)
680 @rm -f demo_jointPR$(EXEEXT)
681 $(demo_jointPR_LINK) $(demo_jointPR_OBJECTS) $(demo_jointPR_LDADD) $(LIBS)
682demo_joints$(EXEEXT): $(demo_joints_OBJECTS) $(demo_joints_DEPENDENCIES)
683 @rm -f demo_joints$(EXEEXT)
684 $(demo_joints_LINK) $(demo_joints_OBJECTS) $(demo_joints_LDADD) $(LIBS)
685demo_motor$(EXEEXT): $(demo_motor_OBJECTS) $(demo_motor_DEPENDENCIES)
686 @rm -f demo_motor$(EXEEXT)
687 $(demo_motor_LINK) $(demo_motor_OBJECTS) $(demo_motor_LDADD) $(LIBS)
688demo_moving_trimesh$(EXEEXT): $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_DEPENDENCIES)
689 @rm -f demo_moving_trimesh$(EXEEXT)
690 $(demo_moving_trimesh_LINK) $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_LDADD) $(LIBS)
691demo_ode$(EXEEXT): $(demo_ode_OBJECTS) $(demo_ode_DEPENDENCIES)
692 @rm -f demo_ode$(EXEEXT)
693 $(demo_ode_LINK) $(demo_ode_OBJECTS) $(demo_ode_LDADD) $(LIBS)
694demo_plane2d$(EXEEXT): $(demo_plane2d_OBJECTS) $(demo_plane2d_DEPENDENCIES)
695 @rm -f demo_plane2d$(EXEEXT)
696 $(demo_plane2d_LINK) $(demo_plane2d_OBJECTS) $(demo_plane2d_LDADD) $(LIBS)
697demo_slider$(EXEEXT): $(demo_slider_OBJECTS) $(demo_slider_DEPENDENCIES)
698 @rm -f demo_slider$(EXEEXT)
699 $(demo_slider_LINK) $(demo_slider_OBJECTS) $(demo_slider_LDADD) $(LIBS)
700demo_space$(EXEEXT): $(demo_space_OBJECTS) $(demo_space_DEPENDENCIES)
701 @rm -f demo_space$(EXEEXT)
702 $(demo_space_LINK) $(demo_space_OBJECTS) $(demo_space_LDADD) $(LIBS)
703demo_space_stress$(EXEEXT): $(demo_space_stress_OBJECTS) $(demo_space_stress_DEPENDENCIES)
704 @rm -f demo_space_stress$(EXEEXT)
705 $(demo_space_stress_LINK) $(demo_space_stress_OBJECTS) $(demo_space_stress_LDADD) $(LIBS)
706demo_step$(EXEEXT): $(demo_step_OBJECTS) $(demo_step_DEPENDENCIES)
707 @rm -f demo_step$(EXEEXT)
708 $(demo_step_LINK) $(demo_step_OBJECTS) $(demo_step_LDADD) $(LIBS)
709demo_trimesh$(EXEEXT): $(demo_trimesh_OBJECTS) $(demo_trimesh_DEPENDENCIES)
710 @rm -f demo_trimesh$(EXEEXT)
711 $(demo_trimesh_LINK) $(demo_trimesh_OBJECTS) $(demo_trimesh_LDADD) $(LIBS)
712
713mostlyclean-compile:
714 -rm -f *.$(OBJEXT)
715
716distclean-compile:
717 -rm -f *.tab.c
718
719@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_I.Po@am__quote@
720@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_basket.Po@am__quote@
721@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_boxstack.Po@am__quote@
722@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_buggy.Po@am__quote@
723@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain1.Po@am__quote@
724@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain2.Po@am__quote@
725@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_collision.Po@am__quote@
726@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_convex_cd.Po@am__quote@
727@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_crash.Po@am__quote@
728@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cyl.Po@am__quote@
729@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cylvssphere.Po@am__quote@
730@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_feedback.Po@am__quote@
731@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_friction.Po@am__quote@
732@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_heightfield.Po@am__quote@
733@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_hinge.Po@am__quote@
734@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_jointPR.Po@am__quote@
735@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_joints.Po@am__quote@
736@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_motor.Po@am__quote@
737@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_moving_trimesh.Po@am__quote@
738@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_ode.Po@am__quote@
739@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_plane2d.Po@am__quote@
740@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_slider.Po@am__quote@
741@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space.Po@am__quote@
742@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space_stress.Po@am__quote@
743@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_step.Po@am__quote@
744@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_trimesh.Po@am__quote@
745
746.c.o:
747@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
748@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
749@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
750@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
751@am__fastdepCC_FALSE@ $(COMPILE) -c $<
752
753.c.obj:
754@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
755@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
756@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
757@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
758@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
759
760.cpp.o:
761@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
762@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
763@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
764@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
765@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
766
767.cpp.obj:
768@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
769@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
770@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
771@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
772@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
773
774ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
775 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
776 unique=`for i in $$list; do \
777 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
778 done | \
779 $(AWK) ' { files[$$0] = 1; } \
780 END { for (i in files) print i; }'`; \
781 mkid -fID $$unique
782tags: TAGS
783
784TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
785 $(TAGS_FILES) $(LISP)
786 tags=; \
787 here=`pwd`; \
788 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
789 unique=`for i in $$list; do \
790 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
791 done | \
792 $(AWK) ' { files[$$0] = 1; } \
793 END { for (i in files) print i; }'`; \
794 if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
795 test -n "$$unique" || unique=$$empty_fix; \
796 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
797 $$tags $$unique; \
798 fi
799ctags: CTAGS
800CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
801 $(TAGS_FILES) $(LISP)
802 tags=; \
803 here=`pwd`; \
804 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
805 unique=`for i in $$list; do \
806 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
807 done | \
808 $(AWK) ' { files[$$0] = 1; } \
809 END { for (i in files) print i; }'`; \
810 test -z "$(CTAGS_ARGS)$$tags$$unique" \
811 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
812 $$tags $$unique
813
814GTAGS:
815 here=`$(am__cd) $(top_builddir) && pwd` \
816 && cd $(top_srcdir) \
817 && gtags -i $(GTAGS_ARGS) $$here
818
819distclean-tags:
820 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
821
822distdir: $(DISTFILES)
823 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
824 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
825 list='$(DISTFILES)'; \
826 dist_files=`for file in $$list; do echo $$file; done | \
827 sed -e "s|^$$srcdirstrip/||;t" \
828 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
829 case $$dist_files in \
830 */*) $(MKDIR_P) `echo "$$dist_files" | \
831 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
832 sort -u` ;; \
833 esac; \
834 for file in $$dist_files; do \
835 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
836 if test -d $$d/$$file; then \
837 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
838 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
839 cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
840 fi; \
841 cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
842 else \
843 test -f $(distdir)/$$file \
844 || cp -p $$d/$$file $(distdir)/$$file \
845 || exit 1; \
846 fi; \
847 done
848check-am: all-am
849check: check-am
850all-am: Makefile $(PROGRAMS)
851installdirs:
852install: install-am
853install-exec: install-exec-am
854install-data: install-data-am
855uninstall: uninstall-am
856
857install-am: all-am
858 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
859
860installcheck: installcheck-am
861install-strip:
862 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
863 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
864 `test -z '$(STRIP)' || \
865 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
866mostlyclean-generic:
867
868clean-generic:
869
870distclean-generic:
871 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
872
873maintainer-clean-generic:
874 @echo "This command is intended for maintainers to use"
875 @echo "it deletes files that may require special tools to rebuild."
876clean: clean-am
877
878clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
879
880distclean: distclean-am
881 -rm -rf ./$(DEPDIR)
882 -rm -f Makefile
883distclean-am: clean-am distclean-compile distclean-generic \
884 distclean-tags
885
886dvi: dvi-am
887
888dvi-am:
889
890html: html-am
891
892info: info-am
893
894info-am:
895
896install-data-am:
897
898install-dvi: install-dvi-am
899
900install-exec-am:
901
902install-html: install-html-am
903
904install-info: install-info-am
905
906install-man:
907
908install-pdf: install-pdf-am
909
910install-ps: install-ps-am
911
912installcheck-am:
913
914maintainer-clean: maintainer-clean-am
915 -rm -rf ./$(DEPDIR)
916 -rm -f Makefile
917maintainer-clean-am: distclean-am maintainer-clean-generic
918
919mostlyclean: mostlyclean-am
920
921mostlyclean-am: mostlyclean-compile mostlyclean-generic
922
923pdf: pdf-am
924
925pdf-am:
926
927ps: ps-am
928
929ps-am:
930
931uninstall-am:
932
933.MAKE: install-am install-strip
934
935.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
936 clean-noinstPROGRAMS ctags distclean distclean-compile \
937 distclean-generic distclean-tags distdir dvi dvi-am html \
938 html-am info info-am install install-am install-data \
939 install-data-am install-dvi install-dvi-am install-exec \
940 install-exec-am install-html install-html-am install-info \
941 install-info-am install-man install-pdf install-pdf-am \
942 install-ps install-ps-am install-strip installcheck \
943 installcheck-am installdirs maintainer-clean \
944 maintainer-clean-generic mostlyclean mostlyclean-compile \
945 mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
946 uninstall-am
947
948
949@WIN32_TRUE@resources.o: ../../drawstuff/src/resources.rc ../../drawstuff/src/resource.h
950@WIN32_TRUE@ @WINDRES@ ../../drawstuff/src/resources.rc -o resources.o
951# Tell versions [3.59,3.63) of GNU make to not export all variables.
952# Otherwise a system limit (for SysV at least) may be exceeded.
953.NOEXPORT:
diff --git a/libraries/ode-0.9/ode/demo/basket_geom.h b/libraries/ode-0.9/ode/demo/basket_geom.h
deleted file mode 100644
index 7796ca8..0000000
--- a/libraries/ode-0.9/ode/demo/basket_geom.h
+++ /dev/null
@@ -1,13 +0,0 @@
1
2static float world_normals[] = {
30,-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,
4};
5
6static float world_vertices[] = {
7-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,
8};
9
10static int world_indices[] = {
110,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,
12};
13
diff --git a/libraries/ode-0.9/ode/demo/demo_I.cpp b/libraries/ode-0.9/ode/demo/demo_I.cpp
deleted file mode 100644
index b4f8d6e..0000000
--- a/libraries/ode-0.9/ode/demo/demo_I.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25test that the rotational physics is correct.
26
27an "anchor body" has a number of other randomly positioned bodies
28("particles") attached to it by ball-and-socket joints, giving it some
29random effective inertia tensor. the effective inertia matrix is calculated,
30and then this inertia is assigned to another "test" body. a random torque is
31applied to both bodies and the difference in angular velocity and orientation
32is observed after a number of iterations.
33
34typical errors for each test cycle are about 1e-5 ... 1e-4.
35
36*/
37
38
39#include <time.h>
40#include <ode/ode.h>
41#include <drawstuff/drawstuff.h>
42
43#ifdef _MSC_VER
44#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
45#endif
46
47// select correct drawing functions
48
49#ifdef dDOUBLE
50#define dsDrawBox dsDrawBoxD
51#define dsDrawSphere dsDrawSphereD
52#define dsDrawCylinder dsDrawCylinderD
53#define dsDrawCapsule dsDrawCapsuleD
54#endif
55
56
57// some constants
58
59#define NUM 10 // number of particles
60#define SIDE 0.1 // visual size of the particles
61
62
63// dynamics objects an globals
64
65static dWorldID world=0;
66static dBodyID anchor_body,particle[NUM],test_body;
67static dJointID particle_joint[NUM];
68static dReal torque[3];
69static int iteration;
70
71
72// start simulation - set viewpoint
73
74static void start()
75{
76 static float xyz[3] = {1.5572f,-1.8886f,1.5700f};
77 static float hpr[3] = {118.5000f,-17.0000f,0.0000f};
78 dsSetViewpoint (xyz,hpr);
79}
80
81
82// compute the mass parameters of a particle set. q = particle positions,
83// pm = particle masses
84
85#define _I(i,j) I[(i)*4+(j)]
86
87void computeMassParams (dMass *m, dReal q[NUM][3], dReal pm[NUM])
88{
89 int i,j;
90 dMassSetZero (m);
91 for (i=0; i<NUM; i++) {
92 m->mass += pm[i];
93 for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
94 m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
95 m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
96 m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
97 m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
98 m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
99 m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
100 }
101 for (j=0; j<3; j++) m->c[j] /= m->mass;
102 m->_I(1,0) = m->_I(0,1);
103 m->_I(2,0) = m->_I(0,2);
104 m->_I(2,1) = m->_I(1,2);
105}
106
107
108void reset_test()
109{
110 int i;
111 dMass m,anchor_m;
112 dReal q[NUM][3], pm[NUM]; // particle positions and masses
113 dReal pos1[3] = {1,0,1}; // point of reference (POR)
114 dReal pos2[3] = {-1,0,1}; // point of reference (POR)
115
116 // make random particle positions (relative to POR) and masses
117 for (i=0; i<NUM; i++) {
118 pm[i] = dRandReal()+0.1;
119 q[i][0] = dRandReal()-0.5;
120 q[i][1] = dRandReal()-0.5;
121 q[i][2] = dRandReal()-0.5;
122 }
123
124 // adjust particle positions so centor of mass = POR
125 computeMassParams (&m,q,pm);
126 for (i=0; i<NUM; i++) {
127 q[i][0] -= m.c[0];
128 q[i][1] -= m.c[1];
129 q[i][2] -= m.c[2];
130 }
131
132 if (world) dWorldDestroy (world);
133 world = dWorldCreate();
134
135 anchor_body = dBodyCreate (world);
136 dBodySetPosition (anchor_body,pos1[0],pos1[1],pos1[2]);
137 dMassSetBox (&anchor_m,1,SIDE,SIDE,SIDE);
138 dMassAdjust (&anchor_m,0.1);
139 dBodySetMass (anchor_body,&anchor_m);
140
141 for (i=0; i<NUM; i++) {
142 particle[i] = dBodyCreate (world);
143 dBodySetPosition (particle[i],
144 pos1[0]+q[i][0],pos1[1]+q[i][1],pos1[2]+q[i][2]);
145 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
146 dMassAdjust (&m,pm[i]);
147 dBodySetMass (particle[i],&m);
148 }
149
150 for (i=0; i < NUM; i++) {
151 particle_joint[i] = dJointCreateBall (world,0);
152 dJointAttach (particle_joint[i],anchor_body,particle[i]);
153 const dReal *p = dBodyGetPosition (particle[i]);
154 dJointSetBallAnchor (particle_joint[i],p[0],p[1],p[2]);
155 }
156
157 // make test_body with the same mass and inertia of the anchor_body plus
158 // all the particles
159
160 test_body = dBodyCreate (world);
161 dBodySetPosition (test_body,pos2[0],pos2[1],pos2[2]);
162 computeMassParams (&m,q,pm);
163 m.mass += anchor_m.mass;
164 for (i=0; i<12; i++) m.I[i] = m.I[i] + anchor_m.I[i];
165 dBodySetMass (test_body,&m);
166
167 // rotate the test and anchor bodies by a random amount
168 dQuaternion qrot;
169 for (i=0; i<4; i++) qrot[i] = dRandReal()-0.5;
170 dNormalize4 (qrot);
171 dBodySetQuaternion (anchor_body,qrot);
172 dBodySetQuaternion (test_body,qrot);
173 dMatrix3 R;
174 dQtoR (qrot,R);
175 for (i=0; i<NUM; i++) {
176 dVector3 v;
177 dMultiply0 (v,R,&q[i][0],3,3,1);
178 dBodySetPosition (particle[i],pos1[0]+v[0],pos1[1]+v[1],pos1[2]+v[2]);
179 }
180
181 // set random torque
182 for (i=0; i<3; i++) torque[i] = (dRandReal()-0.5) * 0.1;
183
184
185 iteration=0;
186}
187
188
189// simulation loop
190
191static void simLoop (int pause)
192{
193 if (!pause) {
194 dBodyAddTorque (anchor_body,torque[0],torque[1],torque[2]);
195 dBodyAddTorque (test_body,torque[0],torque[1],torque[2]);
196 dWorldStep (world,0.03);
197
198 iteration++;
199 if (iteration >= 100) {
200 // measure the difference between the anchor and test bodies
201 const dReal *w1 = dBodyGetAngularVel (anchor_body);
202 const dReal *w2 = dBodyGetAngularVel (test_body);
203 const dReal *q1 = dBodyGetQuaternion (anchor_body);
204 const dReal *q2 = dBodyGetQuaternion (test_body);
205 dReal maxdiff = dMaxDifference (w1,w2,1,3);
206 printf ("w-error = %.4e (%.2f,%.2f,%.2f) and (%.2f,%.2f,%.2f)\n",
207 maxdiff,w1[0],w1[1],w1[2],w2[0],w2[1],w2[2]);
208 maxdiff = dMaxDifference (q1,q2,1,4);
209 printf ("q-error = %.4e\n",maxdiff);
210 reset_test();
211 }
212 }
213
214 dReal sides[3] = {SIDE,SIDE,SIDE};
215 dReal sides2[3] = {6*SIDE,6*SIDE,6*SIDE};
216 dReal sides3[3] = {3*SIDE,3*SIDE,3*SIDE};
217 dsSetColor (1,1,1);
218 dsDrawBox (dBodyGetPosition(anchor_body), dBodyGetRotation(anchor_body),
219 sides3);
220 dsSetColor (1,0,0);
221 dsDrawBox (dBodyGetPosition(test_body), dBodyGetRotation(test_body), sides2);
222 dsSetColor (1,1,0);
223 for (int i=0; i<NUM; i++)
224 dsDrawBox (dBodyGetPosition (particle[i]),
225 dBodyGetRotation (particle[i]), sides);
226}
227
228
229int main (int argc, char **argv)
230{
231 // setup pointers to drawstuff callback functions
232 dsFunctions fn;
233 fn.version = DS_VERSION;
234 fn.start = &start;
235 fn.step = &simLoop;
236 fn.command = 0;
237 fn.stop = 0;
238 fn.path_to_textures = "../../drawstuff/textures";
239 if(argc==2)
240 {
241 fn.path_to_textures = argv[1];
242 }
243
244 dInitODE();
245 dRandSetSeed (time(0));
246 reset_test();
247
248 // run simulation
249 dsSimulationLoop (argc,argv,352,288,&fn);
250
251 dWorldDestroy (world);
252 dCloseODE();
253 return 0;
254}
diff --git a/libraries/ode-0.9/ode/demo/demo_basket.cpp b/libraries/ode-0.9/ode/demo/demo_basket.cpp
deleted file mode 100644
index 35fb49a..0000000
--- a/libraries/ode-0.9/ode/demo/demo_basket.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// Basket ball demo.
24// Serves as a test for the sphere vs trimesh collider
25// By Bram Stolk.
26// Press the spacebar to reset the position of the ball.
27
28#include <ode/config.h>
29#include <assert.h>
30#ifdef HAVE_UNISTD_H
31#include <unistd.h>
32#endif
33#include <ode/ode.h>
34#include <drawstuff/drawstuff.h>
35
36#include "basket_geom.h" // this is our world mesh
37
38#ifdef _MSC_VER
39#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
40#endif
41
42// some constants
43
44#define RADIUS 0.14
45
46// dynamics and collision objects (chassis, 3 wheels, environment)
47
48static dWorldID world;
49static dSpaceID space;
50
51static dBodyID sphbody;
52static dGeomID sphgeom;
53
54static dJointGroupID contactgroup;
55static dGeomID world_mesh;
56
57
58// this is called by dSpaceCollide when two objects in space are
59// potentially colliding.
60
61static void nearCallback (void *data, dGeomID o1, dGeomID o2)
62{
63 assert(o1);
64 assert(o2);
65
66 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
67 {
68 fprintf(stderr,"testing space %p %p\n", o1,o2);
69 // colliding a space with something
70 dSpaceCollide2(o1,o2,data,&nearCallback);
71 // Note we do not want to test intersections within a space,
72 // only between spaces.
73 return;
74 }
75
76// fprintf(stderr,"testing geoms %p %p\n", o1, o2);
77
78 const int N = 32;
79 dContact contact[N];
80 int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
81 if (n > 0)
82 {
83 for (int i=0; i<n; i++)
84 {
85 // Paranoia <-- not working for some people, temporarily removed for 0.6
86 //dIASSERT(dVALIDVEC3(contact[i].geom.pos));
87 //dIASSERT(dVALIDVEC3(contact[i].geom.normal));
88 //dIASSERT(!dIsNan(contact[i].geom.depth));
89 contact[i].surface.slip1 = 0.7;
90 contact[i].surface.slip2 = 0.7;
91 contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
92 contact[i].surface.mu = 50.0; // was: dInfinity
93 contact[i].surface.soft_erp = 0.96;
94 contact[i].surface.soft_cfm = 0.04;
95 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
96 dJointAttach (c,
97 dGeomGetBody(contact[i].geom.g1),
98 dGeomGetBody(contact[i].geom.g2));
99 }
100 }
101}
102
103
104// start simulation - set viewpoint
105
106static void start()
107{
108 static float xyz[3] = {-8,0,5};
109 static float hpr[3] = {0.0f,-29.5000f,0.0000f};
110 dsSetViewpoint (xyz,hpr);
111}
112
113
114
115static void reset_ball(void)
116{
117 float sx=0.0f, sy=3.40f, sz=7.05;
118
119#if defined(_MSC_VER) && defined(dDOUBLE)
120 sy -= 0.01; // Cheat, to make it score under win32/double
121#endif
122
123 dQuaternion q;
124 dQSetIdentity(q);
125 dBodySetPosition (sphbody, sx, sy, sz);
126 dBodySetQuaternion(sphbody, q);
127 dBodySetLinearVel (sphbody, 0,0,0);
128 dBodySetAngularVel (sphbody, 0,0,0);
129}
130
131
132// called when a key pressed
133
134static void command (int cmd)
135{
136 switch (cmd)
137 {
138 case ' ':
139 reset_ball();
140 break;
141 }
142}
143
144
145// simulation loop
146
147static void simLoop (int pause)
148{
149 double simstep = 0.001; // 1ms simulation steps
150 double dt = dsElapsedTime();
151
152 int nrofsteps = (int) ceilf(dt/simstep);
153// fprintf(stderr, "dt=%f, nr of steps = %d\n", dt, nrofsteps);
154
155 for (int i=0; i<nrofsteps && !pause; i++)
156 {
157 dSpaceCollide (space,0,&nearCallback);
158 dWorldQuickStep (world, simstep);
159 dJointGroupEmpty (contactgroup);
160 }
161
162 dsSetColor (1,1,1);
163 const dReal *SPos = dBodyGetPosition(sphbody);
164 const dReal *SRot = dBodyGetRotation(sphbody);
165 float spos[3] = {SPos[0], SPos[1], SPos[2]};
166 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] };
167 dsDrawSphere
168 (
169 spos,
170 srot,
171 RADIUS
172 );
173
174 // draw world trimesh
175 dsSetColor(0.4,0.7,0.9);
176 dsSetTexture (DS_NONE);
177
178 const dReal* Pos = dGeomGetPosition(world_mesh);
179 //dIASSERT(dVALIDVEC3(Pos));
180 float pos[3] = { Pos[0], Pos[1], Pos[2] };
181
182 const dReal* Rot = dGeomGetRotation(world_mesh);
183 //dIASSERT(dVALIDMAT3(Rot));
184 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] };
185
186 int numi = sizeof(world_indices) / sizeof(int);
187
188 for (int i=0; i<numi/3; i++)
189 {
190 int i0 = world_indices[i*3+0];
191 int i1 = world_indices[i*3+1];
192 int i2 = world_indices[i*3+2];
193 float *v0 = world_vertices+i0*3;
194 float *v1 = world_vertices+i1*3;
195 float *v2 = world_vertices+i2*3;
196 dsDrawTriangle(pos, rot, v0,v1,v2, true); // single precision draw
197 }
198}
199
200
201int main (int argc, char **argv)
202{
203 dMass m;
204 dMatrix3 R;
205
206 // setup pointers to drawstuff callback functions
207 dsFunctions fn;
208 fn.version = DS_VERSION;
209 fn.start = &start;
210 fn.step = &simLoop;
211 fn.command = &command;
212 fn.stop = 0;
213 fn.path_to_textures = "../../drawstuff/textures";
214 if(argc==2)
215 fn.path_to_textures = argv[1];
216
217 // create world
218 dInitODE();
219 world = dWorldCreate();
220 space = dHashSpaceCreate (0);
221
222 contactgroup = dJointGroupCreate (0);
223 dWorldSetGravity (world,0,0,-9.8);
224 dWorldSetQuickStepNumIterations (world, 64);
225
226 // Create a static world using a triangle mesh that we can collide with.
227 int numv = sizeof(world_vertices)/(3*sizeof(float));
228 int numi = sizeof(world_indices)/ sizeof(int);
229 printf("numv=%d, numi=%d\n", numv, numi);
230 dTriMeshDataID Data = dGeomTriMeshDataCreate();
231
232// fprintf(stderr,"Building Single Precision Mesh\n");
233
234 dGeomTriMeshDataBuildSingle
235 (
236 Data,
237 world_vertices,
238 3 * sizeof(float),
239 numv,
240 world_indices,
241 numi,
242 3 * sizeof(int)
243 );
244
245 world_mesh = dCreateTriMesh(space, Data, 0, 0, 0);
246 dGeomTriMeshEnableTC(world_mesh, dSphereClass, false);
247 dGeomTriMeshEnableTC(world_mesh, dBoxClass, false);
248 dGeomSetPosition(world_mesh, 0, 0, 0.5);
249 dRSetIdentity(R);
250 //dIASSERT(dVALIDMAT3(R));
251
252 dGeomSetRotation (world_mesh, R);
253
254 float sx=0.0, sy=3.40, sz=6.80;
255 sphbody = dBodyCreate (world);
256 dMassSetSphere (&m,1,RADIUS);
257 dBodySetMass (sphbody,&m);
258 sphgeom = dCreateSphere(0, RADIUS);
259 dGeomSetBody (sphgeom,sphbody);
260 reset_ball();
261 dSpaceAdd (space, sphgeom);
262
263 // run simulation
264 dsSimulationLoop (argc,argv,352,288,&fn);
265
266 // Causes segm violation? Why?
267 // (because dWorldDestroy() destroys body connected to geom; must call first!)
268 dGeomDestroy(sphgeom);
269 dGeomDestroy (world_mesh);
270
271 dJointGroupEmpty (contactgroup);
272 dJointGroupDestroy (contactgroup);
273 dSpaceDestroy (space);
274 dWorldDestroy (world);
275 dCloseODE();
276 return 0;
277}
278
diff --git a/libraries/ode-0.9/ode/demo/demo_boxstack.cpp b/libraries/ode-0.9/ode/demo/demo_boxstack.cpp
deleted file mode 100644
index 8d237b2..0000000
--- a/libraries/ode-0.9/ode/demo/demo_boxstack.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30
31//<---- Convex Object
32dReal planes[]= // planes for a cube, these should coincide with the face array
33 {
34 1.0f ,0.0f ,0.0f ,0.25f,
35 0.0f ,1.0f ,0.0f ,0.25f,
36 0.0f ,0.0f ,1.0f ,0.25f,
37 -1.0f,0.0f ,0.0f ,0.25f,
38 0.0f ,-1.0f,0.0f ,0.25f,
39 0.0f ,0.0f ,-1.0f,0.25f
40 /*
41 1.0f ,0.0f ,0.0f ,2.0f,
42 0.0f ,1.0f ,0.0f ,1.0f,
43 0.0f ,0.0f ,1.0f ,1.0f,
44 0.0f ,0.0f ,-1.0f,1.0f,
45 0.0f ,-1.0f,0.0f ,1.0f,
46 -1.0f,0.0f ,0.0f ,0.0f
47 */
48 };
49const unsigned int planecount=6;
50
51dReal points[]= // points for a cube
52 {
53 0.25f,0.25f,0.25f, // point 0
54 -0.25f,0.25f,0.25f, // point 1
55
56 0.25f,-0.25f,0.25f, // point 2
57 -0.25f,-0.25f,0.25f,// point 3
58
59 0.25f,0.25f,-0.25f, // point 4
60 -0.25f,0.25f,-0.25f,// point 5
61
62 0.25f,-0.25f,-0.25f,// point 6
63 -0.25f,-0.25f,-0.25f,// point 7
64 };
65const unsigned int pointcount=8;
66unsigned int polygons[] = //Polygons for a cube (6 squares)
67 {
68 4,0,2,6,4, // positive X
69 4,1,0,4,5, // positive Y
70 4,0,1,3,2, // positive Z
71 4,3,1,5,7, // negative X
72 4,2,3,7,6, // negative Y
73 4,5,4,6,7, // negative Z
74 };
75//----> Convex Object
76
77// select correct drawing functions
78
79#ifdef dDOUBLE
80#define dsDrawBox dsDrawBoxD
81#define dsDrawSphere dsDrawSphereD
82#define dsDrawCylinder dsDrawCylinderD
83#define dsDrawCapsule dsDrawCapsuleD
84#define dsDrawConvex dsDrawConvexD
85#endif
86
87
88// some constants
89
90#define NUM 100 // max number of objects
91#define DENSITY (5.0) // density of all objects
92#define GPB 3 // maximum number of geometries per body
93#define MAX_CONTACTS 8 // maximum number of contact points per body
94#define USE_GEOM_OFFSET 1
95
96// dynamics and collision objects
97
98struct MyObject {
99 dBodyID body; // the body
100 dGeomID geom[GPB]; // geometries representing this body
101};
102
103static int num=0; // number of objects in simulation
104static int nextobj=0; // next object to recycle if num==NUM
105static dWorldID world;
106static dSpaceID space;
107static MyObject obj[NUM];
108static dJointGroupID contactgroup;
109static int selected = -1; // selected object
110static int show_aabb = 0; // show geom AABBs?
111static int show_contacts = 0; // show contact points?
112static int random_pos = 1; // drop objects from random position?
113static int write_world = 0;
114static int show_body = 1;
115
116// this is called by dSpaceCollide when two objects in space are
117// potentially colliding.
118
119static void nearCallback (void *data, dGeomID o1, dGeomID o2)
120{
121 int i;
122 // if (o1->body && o2->body) return;
123
124 // exit without doing anything if the two bodies are connected by a joint
125 dBodyID b1 = dGeomGetBody(o1);
126 dBodyID b2 = dGeomGetBody(o2);
127 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
128
129 dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
130 for (i=0; i<MAX_CONTACTS; i++) {
131 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
132 contact[i].surface.mu = dInfinity;
133 contact[i].surface.mu2 = 0;
134 contact[i].surface.bounce = 0.1;
135 contact[i].surface.bounce_vel = 0.1;
136 contact[i].surface.soft_cfm = 0.01;
137 }
138 if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
139 sizeof(dContact))) {
140 dMatrix3 RI;
141 dRSetIdentity (RI);
142 const dReal ss[3] = {0.02,0.02,0.02};
143 for (i=0; i<numc; i++) {
144 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
145 dJointAttach (c,b1,b2);
146 if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
147 }
148 }
149}
150
151
152// start simulation - set viewpoint
153
154static void start()
155{
156 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
157 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
158 dsSetViewpoint (xyz,hpr);
159 printf ("To drop another object, press:\n");
160 printf (" b for box.\n");
161 printf (" s for sphere.\n");
162 printf (" c for capsule.\n");
163 printf (" y for cylinder.\n");
164 printf (" v for a convex object.\n");
165 printf (" x for a composite object.\n");
166 printf ("To select an object, press space.\n");
167 printf ("To disable the selected object, press d.\n");
168 printf ("To enable the selected object, press e.\n");
169 printf ("To toggle showing the geom AABBs, press a.\n");
170 printf ("To toggle showing the contact points, press t.\n");
171 printf ("To toggle dropping from random position/orientation, press r.\n");
172 printf ("To save the current state to 'state.dif', press 1.\n");
173}
174
175
176char locase (char c)
177{
178 if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
179 else return c;
180}
181
182
183// called when a key pressed
184
185static void command (int cmd)
186{
187 size_t i;
188 int j,k;
189 dReal sides[3];
190 dMass m;
191 int setBody;
192
193 cmd = locase (cmd);
194 if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'y' || cmd == 'v')
195 {
196 setBody = 0;
197 if (num < NUM) {
198 i = num;
199 num++;
200 }
201 else {
202 i = nextobj;
203 nextobj++;
204 if (nextobj >= num) nextobj = 0;
205
206 // destroy the body and geoms for slot i
207 dBodyDestroy (obj[i].body);
208 for (k=0; k < GPB; k++) {
209 if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
210 }
211 memset (&obj[i],0,sizeof(obj[i]));
212 }
213
214 obj[i].body = dBodyCreate (world);
215 for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
216
217 dMatrix3 R;
218 if (random_pos)
219 {
220 dBodySetPosition (obj[i].body,
221 dRandReal()*2-1,dRandReal()*2-1,dRandReal()+2);
222 dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
223 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
224 }
225 else
226 {
227 dReal maxheight = 0;
228 for (k=0; k<num; k++)
229 {
230 const dReal *pos = dBodyGetPosition (obj[k].body);
231 if (pos[2] > maxheight) maxheight = pos[2];
232 }
233 dBodySetPosition (obj[i].body, 0,0,maxheight+1);
234 dRSetIdentity (R);
235 //dRFromAxisAndAngle (R,0,0,1,/*dRandReal()*10.0-5.0*/0);
236 }
237 dBodySetRotation (obj[i].body,R);
238 dBodySetData (obj[i].body,(void*) i);
239
240 if (cmd == 'b') {
241 dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
242 obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
243 }
244 else if (cmd == 'c') {
245 sides[0] *= 0.5;
246 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
247 obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
248 }
249 //<---- Convex Object
250 else if (cmd == 'v')
251 {
252 dMassSetBox (&m,DENSITY,0.25,0.25,0.25);
253 obj[i].geom[0] = dCreateConvex (space,
254 planes,
255 planecount,
256 points,
257 pointcount,
258 polygons);
259 }
260 //----> Convex Object
261 else if (cmd == 'y') {
262 dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
263 obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
264 }
265 else if (cmd == 's') {
266 sides[0] *= 0.5;
267 dMassSetSphere (&m,DENSITY,sides[0]);
268 obj[i].geom[0] = dCreateSphere (space,sides[0]);
269 }
270 else if (cmd == 'x' && USE_GEOM_OFFSET) {
271 setBody = 1;
272 // start accumulating masses for the encapsulated geometries
273 dMass m2;
274 dMassSetZero (&m);
275
276 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
277 dMatrix3 drot[GPB];
278
279 // set random delta positions
280 for (j=0; j<GPB; j++) {
281 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
282 }
283
284 for (k=0; k<GPB; k++) {
285 if (k==0) {
286 dReal radius = dRandReal()*0.25+0.05;
287 obj[i].geom[k] = dCreateSphere (space,radius);
288 dMassSetSphere (&m2,DENSITY,radius);
289 }
290 else if (k==1) {
291 obj[i].geom[k] = dCreateBox (space,sides[0],sides[1],sides[2]);
292 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
293 }
294 else {
295 dReal radius = dRandReal()*0.1+0.05;
296 dReal length = dRandReal()*1.0+0.1;
297 obj[i].geom[k] = dCreateCapsule (space,radius,length);
298 dMassSetCapsule (&m2,DENSITY,3,radius,length);
299 }
300
301 dRFromAxisAndAngle (drot[k],dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
302 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
303 dMassRotate (&m2,drot[k]);
304
305 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
306
307 // add to the total mass
308 dMassAdd (&m,&m2);
309
310 }
311 for (k=0; k<GPB; k++) {
312 dGeomSetBody (obj[i].geom[k],obj[i].body);
313 dGeomSetOffsetPosition (obj[i].geom[k],
314 dpos[k][0]-m.c[0],
315 dpos[k][1]-m.c[1],
316 dpos[k][2]-m.c[2]);
317 dGeomSetOffsetRotation(obj[i].geom[k], drot[k]);
318 }
319 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
320 dBodySetMass (obj[i].body,&m);
321
322 }
323 else if (cmd == 'x') {
324 dGeomID g2[GPB]; // encapsulated geometries
325 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
326
327 // start accumulating masses for the encapsulated geometries
328 dMass m2;
329 dMassSetZero (&m);
330
331 // set random delta positions
332 for (j=0; j<GPB; j++) {
333 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
334 }
335
336 for (k=0; k<GPB; k++) {
337 obj[i].geom[k] = dCreateGeomTransform (space);
338 dGeomTransformSetCleanup (obj[i].geom[k],1);
339 if (k==0) {
340 dReal radius = dRandReal()*0.25+0.05;
341 g2[k] = dCreateSphere (0,radius);
342 dMassSetSphere (&m2,DENSITY,radius);
343 }
344 else if (k==1) {
345 g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
346 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
347 }
348 else {
349 dReal radius = dRandReal()*0.1+0.05;
350 dReal length = dRandReal()*1.0+0.1;
351 g2[k] = dCreateCapsule (0,radius,length);
352 dMassSetCapsule (&m2,DENSITY,3,radius,length);
353 }
354 dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
355
356 // set the transformation (adjust the mass too)
357 dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
358 dMatrix3 Rtx;
359 dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
360 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
361 dGeomSetRotation (g2[k],Rtx);
362 dMassRotate (&m2,Rtx);
363
364 // Translation *after* rotation
365 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
366
367 // add to the total mass
368 dMassAdd (&m,&m2);
369 }
370
371 // move all encapsulated objects so that the center of mass is (0,0,0)
372 for (k=0; k<GPB; k++) {
373 dGeomSetPosition (g2[k],
374 dpos[k][0]-m.c[0],
375 dpos[k][1]-m.c[1],
376 dpos[k][2]-m.c[2]);
377 }
378 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
379 }
380
381 if (!setBody)
382 for (k=0; k < GPB; k++) {
383 if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
384 }
385
386 dBodySetMass (obj[i].body,&m);
387 }
388
389 if (cmd == ' ') {
390 selected++;
391 if (selected >= num) selected = 0;
392 if (selected < 0) selected = 0;
393 }
394 else if (cmd == 'd' && selected >= 0 && selected < num) {
395 dBodyDisable (obj[selected].body);
396 }
397 else if (cmd == 'e' && selected >= 0 && selected < num) {
398 dBodyEnable (obj[selected].body);
399 }
400 else if (cmd == 'a') {
401 show_aabb ^= 1;
402 }
403 else if (cmd == 't') {
404 show_contacts ^= 1;
405 }
406 else if (cmd == 'r') {
407 random_pos ^= 1;
408 }
409 else if (cmd == '1') {
410 write_world = 1;
411 }
412}
413
414
415// draw a geom
416
417void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
418{
419 int i;
420
421 if (!g) return;
422 if (!pos) pos = dGeomGetPosition (g);
423 if (!R) R = dGeomGetRotation (g);
424
425 int type = dGeomGetClass (g);
426 if (type == dBoxClass) {
427 dVector3 sides;
428 dGeomBoxGetLengths (g,sides);
429 dsDrawBox (pos,R,sides);
430 }
431 else if (type == dSphereClass) {
432 dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
433 }
434 else if (type == dCapsuleClass) {
435 dReal radius,length;
436 dGeomCapsuleGetParams (g,&radius,&length);
437 dsDrawCapsule (pos,R,length,radius);
438 }
439 //<---- Convex Object
440 else if (type == dConvexClass)
441 {
442 //dVector3 sides={0.50,0.50,0.50};
443 dsDrawConvex(pos,R,planes,
444 planecount,
445 points,
446 pointcount,
447 polygons);
448 }
449 //----> Convex Object
450 else if (type == dCylinderClass) {
451 dReal radius,length;
452 dGeomCylinderGetParams (g,&radius,&length);
453 dsDrawCylinder (pos,R,length,radius);
454 }
455 else if (type == dGeomTransformClass) {
456 dGeomID g2 = dGeomTransformGetGeom (g);
457 const dReal *pos2 = dGeomGetPosition (g2);
458 const dReal *R2 = dGeomGetRotation (g2);
459 dVector3 actual_pos;
460 dMatrix3 actual_R;
461 dMULTIPLY0_331 (actual_pos,R,pos2);
462 actual_pos[0] += pos[0];
463 actual_pos[1] += pos[1];
464 actual_pos[2] += pos[2];
465 dMULTIPLY0_333 (actual_R,R,R2);
466 drawGeom (g2,actual_pos,actual_R,0);
467 }
468 if (show_body) {
469 dBodyID body = dGeomGetBody(g);
470 if (body) {
471 const dReal *bodypos = dBodyGetPosition (body);
472 const dReal *bodyr = dBodyGetRotation (body);
473 dReal bodySides[3] = { 0.1, 0.1, 0.1 };
474 dsSetColorAlpha(0,1,0,1);
475 dsDrawBox(bodypos,bodyr,bodySides);
476 }
477 }
478 if (show_aabb) {
479 // draw the bounding box for this geom
480 dReal aabb[6];
481 dGeomGetAABB (g,aabb);
482 dVector3 bbpos;
483 for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
484 dVector3 bbsides;
485 for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
486 dMatrix3 RI;
487 dRSetIdentity (RI);
488 dsSetColorAlpha (1,0,0,0.5);
489 dsDrawBox (bbpos,RI,bbsides);
490 }
491}
492
493
494// simulation loop
495
496static void simLoop (int pause)
497{
498 dsSetColor (0,0,2);
499 dSpaceCollide (space,0,&nearCallback);
500 if (!pause) dWorldQuickStep (world,0.02);
501
502 if (write_world) {
503 FILE *f = fopen ("state.dif","wt");
504 if (f) {
505 dWorldExportDIF (world,f,"X");
506 fclose (f);
507 }
508 write_world = 0;
509 }
510
511 // remove all contact joints
512 dJointGroupEmpty (contactgroup);
513
514 dsSetColor (1,1,0);
515 dsSetTexture (DS_WOOD);
516 for (int i=0; i<num; i++) {
517 for (int j=0; j < GPB; j++) {
518 if (i==selected) {
519 dsSetColor (0,0.7,1);
520 }
521 else if (! dBodyIsEnabled (obj[i].body)) {
522 dsSetColor (1,0.8,0);
523 }
524 else {
525 dsSetColor (1,1,0);
526 }
527 drawGeom (obj[i].geom[j],0,0,show_aabb);
528 }
529 }
530}
531
532
533int main (int argc, char **argv)
534{
535 // setup pointers to drawstuff callback functions
536 dsFunctions fn;
537 fn.version = DS_VERSION;
538 fn.start = &start;
539 fn.step = &simLoop;
540 fn.command = &command;
541 fn.stop = 0;
542 fn.path_to_textures = "../../drawstuff/textures";
543 if(argc==2)
544 {
545 fn.path_to_textures = argv[1];
546 }
547
548 // create world
549 dInitODE();
550 world = dWorldCreate();
551 space = dHashSpaceCreate (0);
552 contactgroup = dJointGroupCreate (0);
553 dWorldSetGravity (world,0,0,-0.5);
554 dWorldSetCFM (world,1e-5);
555 dWorldSetAutoDisableFlag (world,1);
556
557#if 1
558
559 dWorldSetAutoDisableAverageSamplesCount( world, 10 );
560
561#endif
562
563
564 dWorldSetContactMaxCorrectingVel (world,0.1);
565 dWorldSetContactSurfaceLayer (world,0.001);
566 dCreatePlane (space,0,0,1,0);
567 memset (obj,0,sizeof(obj));
568
569 // run simulation
570 dsSimulationLoop (argc,argv,352,288,&fn);
571
572 dJointGroupDestroy (contactgroup);
573 dSpaceDestroy (space);
574 dWorldDestroy (world);
575 dCloseODE();
576 return 0;
577}
diff --git a/libraries/ode-0.9/ode/demo/demo_buggy.cpp b/libraries/ode-0.9/ode/demo/demo_buggy.cpp
deleted file mode 100644
index a482e02..0000000
--- a/libraries/ode-0.9/ode/demo/demo_buggy.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25buggy with suspension.
26this also shows you how to use geom groups.
27
28*/
29
30
31#include <ode/ode.h>
32#include <drawstuff/drawstuff.h>
33
34#ifdef _MSC_VER
35#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
36#endif
37
38// select correct drawing functions
39
40#ifdef dDOUBLE
41#define dsDrawBox dsDrawBoxD
42#define dsDrawSphere dsDrawSphereD
43#define dsDrawCylinder dsDrawCylinderD
44#define dsDrawCapsule dsDrawCapsuleD
45#endif
46
47
48// some constants
49
50#define LENGTH 0.7 // chassis length
51#define WIDTH 0.5 // chassis width
52#define HEIGHT 0.2 // chassis height
53#define RADIUS 0.18 // wheel radius
54#define STARTZ 0.5 // starting height of chassis
55#define CMASS 1 // chassis mass
56#define WMASS 0.2 // wheel mass
57
58
59// dynamics and collision objects (chassis, 3 wheels, environment)
60
61static dWorldID world;
62static dSpaceID space;
63static dBodyID body[4];
64static dJointID joint[3]; // joint[0] is the front wheel
65static dJointGroupID contactgroup;
66static dGeomID ground;
67static dSpaceID car_space;
68static dGeomID box[1];
69static dGeomID sphere[3];
70static dGeomID ground_box;
71
72
73// things that the user controls
74
75static dReal speed=0,steer=0; // user commands
76
77
78
79// this is called by dSpaceCollide when two objects in space are
80// potentially colliding.
81
82static void nearCallback (void *data, dGeomID o1, dGeomID o2)
83{
84 int i,n;
85
86 // only collide things with the ground
87 int g1 = (o1 == ground || o1 == ground_box);
88 int g2 = (o2 == ground || o2 == ground_box);
89 if (!(g1 ^ g2)) return;
90
91 const int N = 10;
92 dContact contact[N];
93 n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
94 if (n > 0) {
95 for (i=0; i<n; i++) {
96 contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
97 dContactSoftERP | dContactSoftCFM | dContactApprox1;
98 contact[i].surface.mu = dInfinity;
99 contact[i].surface.slip1 = 0.1;
100 contact[i].surface.slip2 = 0.1;
101 contact[i].surface.soft_erp = 0.5;
102 contact[i].surface.soft_cfm = 0.3;
103 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
104 dJointAttach (c,
105 dGeomGetBody(contact[i].geom.g1),
106 dGeomGetBody(contact[i].geom.g2));
107 }
108 }
109}
110
111
112// start simulation - set viewpoint
113
114static void start()
115{
116 static float xyz[3] = {0.8317f,-0.9817f,0.8000f};
117 static float hpr[3] = {121.0000f,-27.5000f,0.0000f};
118 dsSetViewpoint (xyz,hpr);
119 printf ("Press:\t'a' to increase speed.\n"
120 "\t'z' to decrease speed.\n"
121 "\t',' to steer left.\n"
122 "\t'.' to steer right.\n"
123 "\t' ' to reset speed and steering.\n"
124 "\t'1' to save the current state to 'state.dif'.\n");
125}
126
127
128// called when a key pressed
129
130static void command (int cmd)
131{
132 switch (cmd) {
133 case 'a': case 'A':
134 speed += 0.3;
135 break;
136 case 'z': case 'Z':
137 speed -= 0.3;
138 break;
139 case ',':
140 steer -= 0.5;
141 break;
142 case '.':
143 steer += 0.5;
144 break;
145 case ' ':
146 speed = 0;
147 steer = 0;
148 break;
149 case '1': {
150 FILE *f = fopen ("state.dif","wt");
151 if (f) {
152 dWorldExportDIF (world,f,"");
153 fclose (f);
154 }
155 }
156 }
157}
158
159
160// simulation loop
161
162static void simLoop (int pause)
163{
164 int i;
165 if (!pause) {
166 // motor
167 dJointSetHinge2Param (joint[0],dParamVel2,-speed);
168 dJointSetHinge2Param (joint[0],dParamFMax2,0.1);
169
170 // steering
171 dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
172 if (v > 0.1) v = 0.1;
173 if (v < -0.1) v = -0.1;
174 v *= 10.0;
175 dJointSetHinge2Param (joint[0],dParamVel,v);
176 dJointSetHinge2Param (joint[0],dParamFMax,0.2);
177 dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
178 dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
179 dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);
180
181 dSpaceCollide (space,0,&nearCallback);
182 dWorldStep (world,0.05);
183
184 // remove all contact joints
185 dJointGroupEmpty (contactgroup);
186 }
187
188 dsSetColor (0,1,1);
189 dsSetTexture (DS_WOOD);
190 dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
191 dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
192 dsSetColor (1,1,1);
193 for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
194 dBodyGetRotation(body[i]),0.02f,RADIUS);
195
196 dVector3 ss;
197 dGeomBoxGetLengths (ground_box,ss);
198 dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
199
200 /*
201 printf ("%.10f %.10f %.10f %.10f\n",
202 dJointGetHingeAngle (joint[1]),
203 dJointGetHingeAngle (joint[2]),
204 dJointGetHingeAngleRate (joint[1]),
205 dJointGetHingeAngleRate (joint[2]));
206 */
207}
208
209
210int main (int argc, char **argv)
211{
212 int i;
213 dMass m;
214
215 // setup pointers to drawstuff callback functions
216 dsFunctions fn;
217 fn.version = DS_VERSION;
218 fn.start = &start;
219 fn.step = &simLoop;
220 fn.command = &command;
221 fn.stop = 0;
222 fn.path_to_textures = "../../drawstuff/textures";
223 if(argc==2)
224 {
225 fn.path_to_textures = argv[1];
226 }
227
228 // create world
229 dInitODE();
230 world = dWorldCreate();
231 space = dHashSpaceCreate (0);
232 contactgroup = dJointGroupCreate (0);
233 dWorldSetGravity (world,0,0,-0.5);
234 ground = dCreatePlane (space,0,0,1,0);
235
236 // chassis body
237 body[0] = dBodyCreate (world);
238 dBodySetPosition (body[0],0,0,STARTZ);
239 dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
240 dMassAdjust (&m,CMASS);
241 dBodySetMass (body[0],&m);
242 box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT);
243 dGeomSetBody (box[0],body[0]);
244
245 // wheel bodies
246 for (i=1; i<=3; i++) {
247 body[i] = dBodyCreate (world);
248 dQuaternion q;
249 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
250 dBodySetQuaternion (body[i],q);
251 dMassSetSphere (&m,1,RADIUS);
252 dMassAdjust (&m,WMASS);
253 dBodySetMass (body[i],&m);
254 sphere[i-1] = dCreateSphere (0,RADIUS);
255 dGeomSetBody (sphere[i-1],body[i]);
256 }
257 dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
258 dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
259 dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);
260
261 // front wheel hinge
262 /*
263 joint[0] = dJointCreateHinge2 (world,0);
264 dJointAttach (joint[0],body[0],body[1]);
265 const dReal *a = dBodyGetPosition (body[1]);
266 dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
267 dJointSetHinge2Axis1 (joint[0],0,0,1);
268 dJointSetHinge2Axis2 (joint[0],0,1,0);
269 */
270
271 // front and back wheel hinges
272 for (i=0; i<3; i++) {
273 joint[i] = dJointCreateHinge2 (world,0);
274 dJointAttach (joint[i],body[0],body[i+1]);
275 const dReal *a = dBodyGetPosition (body[i+1]);
276 dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
277 dJointSetHinge2Axis1 (joint[i],0,0,1);
278 dJointSetHinge2Axis2 (joint[i],0,1,0);
279 }
280
281 // set joint suspension
282 for (i=0; i<3; i++) {
283 dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
284 dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8);
285 }
286
287 // lock back wheels along the steering axis
288 for (i=1; i<3; i++) {
289 // set stops to make sure wheels always stay in alignment
290 dJointSetHinge2Param (joint[i],dParamLoStop,0);
291 dJointSetHinge2Param (joint[i],dParamHiStop,0);
292 // the following alternative method is no good as the wheels may get out
293 // of alignment:
294 // dJointSetHinge2Param (joint[i],dParamVel,0);
295 // dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
296 }
297
298 // create car space and add it to the top level space
299 car_space = dSimpleSpaceCreate (space);
300 dSpaceSetCleanup (car_space,0);
301 dSpaceAdd (car_space,box[0]);
302 dSpaceAdd (car_space,sphere[0]);
303 dSpaceAdd (car_space,sphere[1]);
304 dSpaceAdd (car_space,sphere[2]);
305
306 // environment
307 ground_box = dCreateBox (space,2,1.5,1);
308 dMatrix3 R;
309 dRFromAxisAndAngle (R,0,1,0,-0.15);
310 dGeomSetPosition (ground_box,2,0,-0.34);
311 dGeomSetRotation (ground_box,R);
312
313 // run simulation
314 dsSimulationLoop (argc,argv,352,288,&fn);
315
316 dGeomDestroy (box[0]);
317 dGeomDestroy (sphere[0]);
318 dGeomDestroy (sphere[1]);
319 dGeomDestroy (sphere[2]);
320 dJointGroupDestroy (contactgroup);
321 dSpaceDestroy (space);
322 dWorldDestroy (world);
323 dCloseODE();
324 return 0;
325}
diff --git a/libraries/ode-0.9/ode/demo/demo_chain1.c b/libraries/ode-0.9/ode/demo/demo_chain1.c
deleted file mode 100644
index e20c5dc..0000000
--- a/libraries/ode-0.9/ode/demo/demo_chain1.c
+++ /dev/null
@@ -1,171 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/* exercise the C interface */
24
25#include <stdio.h>
26#include "ode/ode.h"
27#include "drawstuff/drawstuff.h"
28
29#ifdef _MSC_VER
30#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
31#endif
32
33/* select correct drawing functions */
34
35#ifdef dDOUBLE
36#define dsDrawBox dsDrawBoxD
37#define dsDrawSphere dsDrawSphereD
38#define dsDrawCylinder dsDrawCylinderD
39#define dsDrawCapsule dsDrawCapsuleD
40#endif
41
42
43/* some constants */
44
45#define NUM 10 /* number of boxes */
46#define SIDE (0.2) /* side length of a box */
47#define MASS (1.0) /* mass of a box */
48#define RADIUS (0.1732f) /* sphere radius */
49
50
51/* dynamics and collision objects */
52
53static dWorldID world;
54static dSpaceID space;
55static dBodyID body[NUM];
56static dJointID joint[NUM-1];
57static dJointGroupID contactgroup;
58static dGeomID sphere[NUM];
59
60
61/* this is called by dSpaceCollide when two objects in space are
62 * potentially colliding.
63 */
64
65static void nearCallback (void *data, dGeomID o1, dGeomID o2)
66{
67 /* exit without doing anything if the two bodies are connected by a joint */
68 dBodyID b1,b2;
69 dContact contact;
70
71 b1 = dGeomGetBody(o1);
72 b2 = dGeomGetBody(o2);
73 if (b1 && b2 && dAreConnected (b1,b2)) return;
74
75 contact.surface.mode = 0;
76 contact.surface.mu = 0.1;
77 contact.surface.mu2 = 0;
78 if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
79 dJointID c = dJointCreateContact (world,contactgroup,&contact);
80 dJointAttach (c,b1,b2);
81 }
82}
83
84
85/* start simulation - set viewpoint */
86
87static void start()
88{
89 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
90 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
91 dsSetViewpoint (xyz,hpr);
92}
93
94
95/* simulation loop */
96
97static void simLoop (int pause)
98{
99 int i;
100 if (!pause) {
101 static double angle = 0;
102 angle += 0.05;
103 dBodyAddForce (body[NUM-1],0,0,1.5*(sin(angle)+1.0));
104
105 dSpaceCollide (space,0,&nearCallback);
106 dWorldStep (world,0.05);
107
108 /* remove all contact joints */
109 dJointGroupEmpty (contactgroup);
110 }
111
112 dsSetColor (1,1,0);
113 dsSetTexture (DS_WOOD);
114 for (i=0; i<NUM; i++) dsDrawSphere (dBodyGetPosition(body[i]),
115 dBodyGetRotation(body[i]),RADIUS);
116}
117
118
119int main (int argc, char **argv)
120{
121 int i;
122 dReal k;
123 dMass m;
124
125 /* setup pointers to drawstuff callback functions */
126 dsFunctions fn;
127 fn.version = DS_VERSION;
128 fn.start = &start;
129 fn.step = &simLoop;
130 fn.command = 0;
131 fn.stop = 0;
132 fn.path_to_textures = "../../drawstuff/textures";
133 if(argc==2)
134 {
135 fn.path_to_textures = argv[1];
136 }
137
138 /* create world */
139 dInitODE();
140 world = dWorldCreate();
141 space = dHashSpaceCreate (0);
142 contactgroup = dJointGroupCreate (1000000);
143 dWorldSetGravity (world,0,0,-0.5);
144 dCreatePlane (space,0,0,1,0);
145
146 for (i=0; i<NUM; i++) {
147 body[i] = dBodyCreate (world);
148 k = i*SIDE;
149 dBodySetPosition (body[i],k,k,k+0.4);
150 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
151 dMassAdjust (&m,MASS);
152 dBodySetMass (body[i],&m);
153 sphere[i] = dCreateSphere (space,RADIUS);
154 dGeomSetBody (sphere[i],body[i]);
155 }
156 for (i=0; i<(NUM-1); i++) {
157 joint[i] = dJointCreateBall (world,0);
158 dJointAttach (joint[i],body[i],body[i+1]);
159 k = (i+0.5)*SIDE;
160 dJointSetBallAnchor (joint[i],k,k,k+0.4);
161 }
162
163 /* run simulation */
164 dsSimulationLoop (argc,argv,352,288,&fn);
165
166 dJointGroupDestroy (contactgroup);
167 dSpaceDestroy (space);
168 dWorldDestroy (world);
169 dCloseODE();
170 return 0;
171}
diff --git a/libraries/ode-0.9/ode/demo/demo_chain2.cpp b/libraries/ode-0.9/ode/demo/demo_chain2.cpp
deleted file mode 100644
index cf35971..0000000
--- a/libraries/ode-0.9/ode/demo/demo_chain2.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/* exercise the C++ interface */
24
25#include <ode/ode.h>
26#include <drawstuff/drawstuff.h>
27
28#ifdef _MSC_VER
29#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
30#endif
31
32// select correct drawing functions
33
34#ifdef dDOUBLE
35#define dsDrawBox dsDrawBoxD
36#define dsDrawSphere dsDrawSphereD
37#define dsDrawCylinder dsDrawCylinderD
38#define dsDrawCapsule dsDrawCapsuleD
39#endif
40
41
42// some constants
43
44#define NUM 10 // number of boxes
45#define SIDE (0.2) // side length of a box
46#define MASS (1.0) // mass of a box
47#define RADIUS (0.1732f) // sphere radius
48
49
50// dynamics and collision objects
51
52static dWorld world;
53static dSimpleSpace space (0);
54static dBody body[NUM];
55static dBallJoint joint[NUM-1];
56static dJointGroup contactgroup;
57static dBox box[NUM];
58
59
60// this is called by space.collide when two objects in space are
61// potentially colliding.
62
63static void nearCallback (void *data, dGeomID o1, dGeomID o2)
64{
65 // exit without doing anything if the two bodies are connected by a joint
66 dBodyID b1 = dGeomGetBody(o1);
67 dBodyID b2 = dGeomGetBody(o2);
68 if (b1 && b2 && dAreConnected (b1,b2)) return;
69
70 // @@@ it's still more convenient to use the C interface here.
71
72 dContact contact;
73 contact.surface.mode = 0;
74 contact.surface.mu = dInfinity;
75 if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
76 dJointID c = dJointCreateContact (world.id(),contactgroup.id(),&contact);
77 dJointAttach (c,b1,b2);
78 }
79}
80
81
82// start simulation - set viewpoint
83
84static void start()
85{
86 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
87 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
88 dsSetViewpoint (xyz,hpr);
89}
90
91
92// simulation loop
93
94static void simLoop (int pause)
95{
96 if (!pause) {
97 static double angle = 0;
98 angle += 0.05;
99 body[NUM-1].addForce (0,0,1.5*(sin(angle)+1.0));
100
101 space.collide (0,&nearCallback);
102 world.step (0.05);
103
104 // remove all contact joints
105 contactgroup.empty();
106 }
107
108 dReal sides[3] = {SIDE,SIDE,SIDE};
109 dsSetColor (1,1,0);
110 dsSetTexture (DS_WOOD);
111 for (int i=0; i<NUM; i++)
112 dsDrawBox (body[i].getPosition(),body[i].getRotation(),sides);
113}
114
115
116int main (int argc, char **argv)
117{
118 // setup pointers to drawstuff callback functions
119 dsFunctions fn;
120 fn.version = DS_VERSION;
121 fn.start = &start;
122 fn.step = &simLoop;
123 fn.command = 0;
124 fn.stop = 0;
125 fn.path_to_textures = "../../drawstuff/textures";
126 if(argc==2)
127 {
128 fn.path_to_textures = argv[1];
129 }
130
131 // create world
132 dInitODE();
133
134 int i;
135 contactgroup.create (0);
136 world.setGravity (0,0,-0.5);
137 dWorldSetCFM (world.id(),1e-5);
138 dPlane plane (space,0,0,1,0);
139
140 for (i=0; i<NUM; i++) {
141 body[i].create (world);
142 dReal k = i*SIDE;
143 body[i].setPosition (k,k,k+0.4);
144 dMass m;
145 m.setBox (1,SIDE,SIDE,SIDE);
146 m.adjust (MASS);
147 body[i].setMass (&m);
148 body[i].setData ((void*)(size_t)i);
149
150 box[i].create (space,SIDE,SIDE,SIDE);
151 box[i].setBody (body[i]);
152 }
153 for (i=0; i<(NUM-1); i++) {
154 joint[i].create (world);
155 joint[i].attach (body[i],body[i+1]);
156 dReal k = (i+0.5)*SIDE;
157 joint[i].setAnchor (k,k,k+0.4);
158 }
159
160 // run simulation
161 dsSimulationLoop (argc,argv,352,288,&fn);
162
163 dCloseODE();
164 return 0;
165}
diff --git a/libraries/ode-0.9/ode/demo/demo_collision.cpp b/libraries/ode-0.9/ode/demo/demo_collision.cpp
deleted file mode 100644
index 8f591e9..0000000
--- a/libraries/ode-0.9/ode/demo/demo_collision.cpp
+++ /dev/null
@@ -1,1371 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25collision tests. if this program is run without any arguments it will
26perform all the tests multiple times, with different random data for each
27test. if this program is given a test number it will run that test
28graphically/interactively, in which case the space bar can be used to
29change the random test conditions.
30
31*/
32
33
34#include <ode/ode.h>
35#include <drawstuff/drawstuff.h>
36
37#ifdef _MSC_VER
38#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
39#endif
40
41// select correct drawing functions
42#ifdef dDOUBLE
43#define dsDrawSphere dsDrawSphereD
44#define dsDrawBox dsDrawBoxD
45#define dsDrawLine dsDrawLineD
46#define dsDrawCapsule dsDrawCapsuleD
47#endif
48
49//****************************************************************************
50// test infrastructure, including constants and macros
51
52#define TEST_REPS1 1000 // run each test this many times (first batch)
53#define TEST_REPS2 10000 // run each test this many times (second batch)
54const dReal tol = 1e-8; // tolerance used for numerical checks
55#define MAX_TESTS 1000 // maximum number of test slots
56#define Z_OFFSET 2 // z offset for drawing (to get above ground)
57
58
59// test function. returns 1 if the test passed or 0 if it failed
60typedef int test_function_t();
61
62struct TestSlot {
63 int number; // number of test
64 char *name; // name of test
65 int failcount;
66 test_function_t *test_fn;
67 int last_failed_line;
68};
69TestSlot testslot[MAX_TESTS];
70
71
72// globals used by the test functions
73int graphical_test=0; // show graphical results of this test, 0=none
74int current_test; // currently execiting test
75int draw_all_objects_called;
76
77
78#define MAKE_TEST(number,function) \
79 if (testslot[number].name) dDebug (0,"test number already used"); \
80 if (number <= 0 || number >= MAX_TESTS) dDebug (0,"bad test number"); \
81 testslot[number].name = # function; \
82 testslot[number].test_fn = function;
83
84#define FAILED() { if (graphical_test==0) { \
85 testslot[current_test].last_failed_line=__LINE__; return 0; } }
86#define PASSED() { return 1; }
87
88//****************************************************************************
89// globals
90
91/* int dBoxBox (const dVector3 p1, const dMatrix3 R1,
92 const dVector3 side1, const dVector3 p2,
93 const dMatrix3 R2, const dVector3 side2,
94 dVector3 normal, dReal *depth, int *code,
95 int maxc, dContactGeom *contact, int skip); */
96
97void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
98 const dVector3 pb, const dVector3 ub,
99 dReal *alpha, dReal *beta);
100
101//****************************************************************************
102// draw all objects in a space, and draw all the collision contact points
103
104void nearCallback (void *data, dGeomID o1, dGeomID o2)
105{
106 int i,j,n;
107 const int N = 100;
108 dContactGeom contact[N];
109
110 if (dGeomGetClass (o2) == dRayClass) {
111 n = dCollide (o2,o1,N,&contact[0],sizeof(dContactGeom));
112 }
113 else {
114 n = dCollide (o1,o2,N,&contact[0],sizeof(dContactGeom));
115 }
116 if (n > 0) {
117 dMatrix3 RI;
118 dRSetIdentity (RI);
119 const dReal ss[3] = {0.01,0.01,0.01};
120 for (i=0; i<n; i++) {
121 contact[i].pos[2] += Z_OFFSET;
122 dsDrawBox (contact[i].pos,RI,ss);
123 dVector3 n;
124 for (j=0; j<3; j++) n[j] = contact[i].pos[j] + 0.1*contact[i].normal[j];
125 dsDrawLine (contact[i].pos,n);
126 }
127 }
128}
129
130
131void draw_all_objects (dSpaceID space)
132{
133 int i, j;
134
135 draw_all_objects_called = 1;
136 if (!graphical_test) return;
137 int n = dSpaceGetNumGeoms (space);
138
139 // draw all contact points
140 dsSetColor (0,1,1);
141 dSpaceCollide (space,0,&nearCallback);
142
143 // draw all rays
144 for (i=0; i<n; i++) {
145 dGeomID g = dSpaceGetGeom (space,i);
146 if (dGeomGetClass (g) == dRayClass) {
147 dsSetColor (1,1,1);
148 dVector3 origin,dir;
149 dGeomRayGet (g,origin,dir);
150 origin[2] += Z_OFFSET;
151 dReal length = dGeomRayGetLength (g);
152 for (j=0; j<3; j++) dir[j] = dir[j]*length + origin[j];
153 dsDrawLine (origin,dir);
154 dsSetColor (0,0,1);
155 dsDrawSphere (origin,dGeomGetRotation(g),0.01);
156 }
157 }
158
159 // draw all other objects
160 for (i=0; i<n; i++) {
161 dGeomID g = dSpaceGetGeom (space,i);
162 dVector3 pos;
163 if (dGeomGetClass (g) != dPlaneClass) {
164 memcpy (pos,dGeomGetPosition(g),sizeof(pos));
165 pos[2] += Z_OFFSET;
166 }
167
168 switch (dGeomGetClass (g)) {
169
170 case dSphereClass: {
171 dsSetColorAlpha (1,0,0,0.8);
172 dReal radius = dGeomSphereGetRadius (g);
173 dsDrawSphere (pos,dGeomGetRotation(g),radius);
174 break;
175 }
176
177 case dBoxClass: {
178 dsSetColorAlpha (1,1,0,0.8);
179 dVector3 sides;
180 dGeomBoxGetLengths (g,sides);
181 dsDrawBox (pos,dGeomGetRotation(g),sides);
182 break;
183 }
184
185 case dCapsuleClass: {
186 dsSetColorAlpha (0,1,0,0.8);
187 dReal radius,length;
188 dGeomCapsuleGetParams (g,&radius,&length);
189 dsDrawCapsule (pos,dGeomGetRotation(g),length,radius);
190 break;
191 }
192
193 case dPlaneClass: {
194 dVector4 n;
195 dMatrix3 R,sides;
196 dVector3 pos2;
197 dGeomPlaneGetParams (g,n);
198 dRFromZAxis (R,n[0],n[1],n[2]);
199 for (j=0; j<3; j++) pos[j] = n[j]*n[3];
200 pos[2] += Z_OFFSET;
201 sides[0] = 2;
202 sides[1] = 2;
203 sides[2] = 0.001;
204 dsSetColor (1,0,1);
205 for (j=0; j<3; j++) pos2[j] = pos[j] + 0.1*n[j];
206 dsDrawLine (pos,pos2);
207 dsSetColorAlpha (1,0,1,0.8);
208 dsDrawBox (pos,R,sides);
209 break;
210 }
211
212 }
213 }
214}
215
216//****************************************************************************
217// point depth tests
218
219int test_sphere_point_depth()
220{
221 int j;
222 dVector3 p,q;
223 dMatrix3 R;
224 dReal r,d;
225
226 dSimpleSpace space(0);
227 dGeomID sphere = dCreateSphere (0,1);
228 dSpaceAdd (space,sphere);
229
230 // ********** make a random sphere of radius r at position p
231
232 r = dRandReal()+0.1;
233 dGeomSphereSetRadius (sphere,r);
234 dMakeRandomVector (p,3,1.0);
235 dGeomSetPosition (sphere,p[0],p[1],p[2]);
236 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
237 dRandReal()*2-1,dRandReal()*10-5);
238 dGeomSetRotation (sphere,R);
239
240 // ********** test center point has depth r
241
242 if (dFabs(dGeomSpherePointDepth (sphere,p[0],p[1],p[2]) - r) > tol) FAILED();
243
244 // ********** test point on surface has depth 0
245
246 for (j=0; j<3; j++) q[j] = dRandReal()-0.5;
247 dNormalize3 (q);
248 for (j=0; j<3; j++) q[j] = q[j]*r + p[j];
249 if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])) > tol) FAILED();
250
251 // ********** test point at random depth
252
253 d = (dRandReal()*2-1) * r;
254 for (j=0; j<3; j++) q[j] = dRandReal()-0.5;
255 dNormalize3 (q);
256 for (j=0; j<3; j++) q[j] = q[j]*(r-d) + p[j];
257 if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])-d) > tol) FAILED();
258
259 PASSED();
260}
261
262
263int test_box_point_depth()
264{
265 int i,j;
266 dVector3 s,p,q,q2; // s = box sides
267 dMatrix3 R;
268 dReal ss,d; // ss = smallest side
269
270 dSimpleSpace space(0);
271 dGeomID box = dCreateBox (0,1,1,1);
272 dSpaceAdd (space,box);
273
274 // ********** make a random box
275
276 for (j=0; j<3; j++) s[j] = dRandReal() + 0.1;
277 dGeomBoxSetLengths (box,s[0],s[1],s[2]);
278 dMakeRandomVector (p,3,1.0);
279 dGeomSetPosition (box,p[0],p[1],p[2]);
280 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
281 dRandReal()*2-1,dRandReal()*10-5);
282 dGeomSetRotation (box,R);
283
284 // ********** test center point has depth of smallest side
285
286 ss = 1e9;
287 for (j=0; j<3; j++) if (s[j] < ss) ss = s[j];
288 if (dFabs(dGeomBoxPointDepth (box,p[0],p[1],p[2]) - 0.5*ss) > tol)
289 FAILED();
290
291 // ********** test point on surface has depth 0
292
293 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
294 i = dRandInt (3);
295 if (dRandReal() > 0.5) q[i] = 0.5*s[i]; else q[i] = -0.5*s[i];
296 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
297 for (j=0; j<3; j++) q2[j] += p[j];
298 if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2])) > tol) FAILED();
299
300 // ********** test points outside box have -ve depth
301
302 for (j=0; j<3; j++) {
303 q[j] = 0.5*s[j] + dRandReal() + 0.01;
304 if (dRandReal() > 0.5) q[j] = -q[j];
305 }
306 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
307 for (j=0; j<3; j++) q2[j] += p[j];
308 if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) >= 0) FAILED();
309
310 // ********** test points inside box have +ve depth
311
312 for (j=0; j<3; j++) q[j] = s[j] * 0.99 * (dRandReal()-0.5);
313 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
314 for (j=0; j<3; j++) q2[j] += p[j];
315 if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) <= 0) FAILED();
316
317 // ********** test random depth of point aligned along axis (up to ss deep)
318
319 i = dRandInt (3);
320 for (j=0; j<3; j++) q[j] = 0;
321 d = (dRandReal()*(ss*0.5+1)-1);
322 q[i] = s[i]*0.5 - d;
323 if (dRandReal() > 0.5) q[i] = -q[i];
324 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
325 for (j=0; j<3; j++) q2[j] += p[j];
326 if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) - d) >= tol) FAILED();
327
328 PASSED();
329}
330
331
332int test_ccylinder_point_depth()
333{
334 int j;
335 dVector3 p,a;
336 dMatrix3 R;
337 dReal r,l,beta,x,y,d;
338
339 dSimpleSpace space(0);
340 dGeomID ccyl = dCreateCapsule (0,1,1);
341 dSpaceAdd (space,ccyl);
342
343 // ********** make a random ccyl
344
345 r = dRandReal()*0.5 + 0.01;
346 l = dRandReal()*1 + 0.01;
347 dGeomCapsuleSetParams (ccyl,r,l);
348 dMakeRandomVector (p,3,1.0);
349 dGeomSetPosition (ccyl,p[0],p[1],p[2]);
350 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
351 dRandReal()*2-1,dRandReal()*10-5);
352 dGeomSetRotation (ccyl,R);
353
354 // ********** test point on axis has depth of 'radius'
355
356 beta = dRandReal()-0.5;
357 for (j=0; j<3; j++) a[j] = p[j] + l*beta*R[j*4+2];
358 if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - r) >= tol)
359 FAILED();
360
361 // ********** test point on surface (excluding caps) has depth 0
362
363 beta = dRandReal()*2*M_PI;
364 x = r*sin(beta);
365 y = r*cos(beta);
366 beta = dRandReal()-0.5;
367 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];
368 if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED();
369
370 // ********** test point on surface of caps has depth 0
371
372 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
373 dNormalize3 (a);
374 if (dDOT14(a,R+2) > 0) {
375 for (j=0; j<3; j++) a[j] = p[j] + a[j]*r + l*0.5*R[j*4+2];
376 }
377 else {
378 for (j=0; j<3; j++) a[j] = p[j] + a[j]*r - l*0.5*R[j*4+2];
379 }
380 if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED();
381
382 // ********** test point inside ccyl has positive depth
383
384 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
385 dNormalize3 (a);
386 beta = dRandReal()-0.5;
387 for (j=0; j<3; j++) a[j] = p[j] + a[j]*r*0.99 + l*beta*R[j*4+2];
388 if (dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) < 0) FAILED();
389
390 // ********** test point depth (1)
391
392 d = (dRandReal()*2-1) * r;
393 beta = dRandReal()*2*M_PI;
394 x = (r-d)*sin(beta);
395 y = (r-d)*cos(beta);
396 beta = dRandReal()-0.5;
397 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];
398 if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol)
399 FAILED();
400
401 // ********** test point depth (2)
402
403 d = (dRandReal()*2-1) * r;
404 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
405 dNormalize3 (a);
406 if (dDOT14(a,R+2) > 0) {
407 for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) + l*0.5*R[j*4+2];
408 }
409 else {
410 for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) - l*0.5*R[j*4+2];
411 }
412 if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol)
413 FAILED();
414
415 PASSED();
416}
417
418
419int test_plane_point_depth()
420{
421 int j;
422 dVector3 n,p,q,a,b; // n = plane normal
423 dReal d;
424
425 dSimpleSpace space(0);
426 dGeomID plane = dCreatePlane (0,0,0,1,0);
427 dSpaceAdd (space,plane);
428
429 // ********** make a random plane
430
431 for (j=0; j<3; j++) n[j] = dRandReal() - 0.5;
432 dNormalize3 (n);
433 d = dRandReal() - 0.5;
434 dGeomPlaneSetParams (plane,n[0],n[1],n[2],d);
435 dPlaneSpace (n,p,q);
436
437 // ********** test point on plane has depth 0
438
439 a[0] = dRandReal() - 0.5;
440 a[1] = dRandReal() - 0.5;
441 a[2] = 0;
442 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
443 if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2])) >= tol) FAILED();
444
445 // ********** test arbitrary depth point
446
447 a[0] = dRandReal() - 0.5;
448 a[1] = dRandReal() - 0.5;
449 a[2] = dRandReal() - 0.5;
450 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
451 if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) + a[2]) >= tol)
452 FAILED();
453
454 // ********** test depth-1 point
455
456 a[0] = dRandReal() - 0.5;
457 a[1] = dRandReal() - 0.5;
458 a[2] = -1;
459 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
460 if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) - 1) >= tol) FAILED();
461
462 PASSED();
463}
464
465//****************************************************************************
466// ray tests
467
468int test_ray_and_sphere()
469{
470 int j;
471 dContactGeom contact;
472 dVector3 p,q,q2,n,v1;
473 dMatrix3 R;
474 dReal r,k;
475
476 dSimpleSpace space(0);
477 dGeomID ray = dCreateRay (0,0);
478 dGeomID sphere = dCreateSphere (0,1);
479 dSpaceAdd (space,ray);
480 dSpaceAdd (space,sphere);
481
482 // ********** make a random sphere of radius r at position p
483
484 r = dRandReal()+0.1;
485 dGeomSphereSetRadius (sphere,r);
486 dMakeRandomVector (p,3,1.0);
487 dGeomSetPosition (sphere,p[0],p[1],p[2]);
488 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
489 dRandReal()*2-1,dRandReal()*10-5);
490 dGeomSetRotation (sphere,R);
491
492 // ********** test zero length ray just inside sphere
493
494 dGeomRaySetLength (ray,0);
495 dMakeRandomVector (q,3,1.0);
496 dNormalize3 (q);
497 for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j];
498 dGeomSetPosition (ray,q[0],q[1],q[2]);
499 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
500 dRandReal()*2-1,dRandReal()*10-5);
501 dGeomSetRotation (ray,R);
502 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
503
504 // ********** test zero length ray just outside that sphere
505
506 dGeomRaySetLength (ray,0);
507 dMakeRandomVector (q,3,1.0);
508 dNormalize3 (q);
509 for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
510 dGeomSetPosition (ray,q[0],q[1],q[2]);
511 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
512 dRandReal()*2-1,dRandReal()*10-5);
513 dGeomSetRotation (ray,R);
514 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
515
516 // ********** test finite length ray totally contained inside the sphere
517
518 dMakeRandomVector (q,3,1.0);
519 dNormalize3 (q);
520 k = dRandReal();
521 for (j=0; j<3; j++) q[j] = k*r*0.99 * q[j] + p[j];
522 dMakeRandomVector (q2,3,1.0);
523 dNormalize3 (q2);
524 k = dRandReal();
525 for (j=0; j<3; j++) q2[j] = k*r*0.99 * q2[j] + p[j];
526 for (j=0; j<3; j++) n[j] = q2[j] - q[j];
527 dNormalize3 (n);
528 dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
529 dGeomRaySetLength (ray,dDISTANCE (q,q2));
530 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
531
532 // ********** test finite length ray totally outside the sphere
533
534 dMakeRandomVector (q,3,1.0);
535 dNormalize3 (q);
536 do {
537 dMakeRandomVector (n,3,1.0);
538 dNormalize3 (n);
539 }
540 while (dDOT(n,q) < 0); // make sure normal goes away from sphere
541 for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
542 dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
543 dGeomRaySetLength (ray,100);
544 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
545
546 // ********** test ray from outside to just above surface
547
548 dMakeRandomVector (q,3,1.0);
549 dNormalize3 (q);
550 for (j=0; j<3; j++) n[j] = -q[j];
551 for (j=0; j<3; j++) q2[j] = 2*r * q[j] + p[j];
552 dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]);
553 dGeomRaySetLength (ray,0.99*r);
554 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
555
556 // ********** test ray from outside to just below surface
557
558 dGeomRaySetLength (ray,1.01*r);
559 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
560 for (j=0; j<3; j++) q2[j] = r * q[j] + p[j];
561 if (dDISTANCE (contact.pos,q2) > tol) FAILED();
562
563 // ********** test contact point distance for random rays
564
565 dMakeRandomVector (q,3,1.0);
566 dNormalize3 (q);
567 k = dRandReal()+0.5;
568 for (j=0; j<3; j++) q[j] = k*r * q[j] + p[j];
569 dMakeRandomVector (n,3,1.0);
570 dNormalize3 (n);
571 dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
572 dGeomRaySetLength (ray,100);
573 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom))) {
574 k = dDISTANCE (contact.pos,dGeomGetPosition(sphere));
575 if (dFabs(k - r) > tol) FAILED();
576 // also check normal signs
577 if (dDOT (n,contact.normal) > 0) FAILED();
578 // also check depth of contact point
579 if (dFabs (dGeomSpherePointDepth
580 (sphere,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
581 FAILED();
582
583 draw_all_objects (space);
584 }
585
586 // ********** test tangential grazing - miss
587
588 dMakeRandomVector (q,3,1.0);
589 dNormalize3 (q);
590 dPlaneSpace (q,n,v1);
591 for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
592 for (j=0; j<3; j++) q[j] -= n[j];
593 dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
594 dGeomRaySetLength (ray,2);
595 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
596
597 // ********** test tangential grazing - hit
598
599 dMakeRandomVector (q,3,1.0);
600 dNormalize3 (q);
601 dPlaneSpace (q,n,v1);
602 for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j];
603 for (j=0; j<3; j++) q[j] -= n[j];
604 dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
605 dGeomRaySetLength (ray,2);
606 if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
607
608 PASSED();
609}
610
611
612int test_ray_and_box()
613{
614 int i,j;
615 dContactGeom contact;
616 dVector3 s,p,q,n,q2,q3,q4; // s = box sides
617 dMatrix3 R;
618 dReal k;
619
620 dSimpleSpace space(0);
621 dGeomID ray = dCreateRay (0,0);
622 dGeomID box = dCreateBox (0,1,1,1);
623 dSpaceAdd (space,ray);
624 dSpaceAdd (space,box);
625
626 // ********** make a random box
627
628 for (j=0; j<3; j++) s[j] = dRandReal() + 0.1;
629 dGeomBoxSetLengths (box,s[0],s[1],s[2]);
630 dMakeRandomVector (p,3,1.0);
631 dGeomSetPosition (box,p[0],p[1],p[2]);
632 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
633 dRandReal()*2-1,dRandReal()*10-5);
634 dGeomSetRotation (box,R);
635
636 // ********** test zero length ray just inside box
637
638 dGeomRaySetLength (ray,0);
639 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
640 i = dRandInt (3);
641 if (dRandReal() > 0.5) q[i] = 0.99*0.5*s[i]; else q[i] = -0.99*0.5*s[i];
642 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
643 for (j=0; j<3; j++) q2[j] += p[j];
644 dGeomSetPosition (ray,q2[0],q2[1],q2[2]);
645 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
646 dRandReal()*2-1,dRandReal()*10-5);
647 dGeomSetRotation (ray,R);
648 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
649
650 // ********** test zero length ray just outside box
651
652 dGeomRaySetLength (ray,0);
653 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
654 i = dRandInt (3);
655 if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
656 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
657 for (j=0; j<3; j++) q2[j] += p[j];
658 dGeomSetPosition (ray,q2[0],q2[1],q2[2]);
659 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
660 dRandReal()*2-1,dRandReal()*10-5);
661 dGeomSetRotation (ray,R);
662 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
663
664 // ********** test finite length ray totally contained inside the box
665
666 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*0.99*s[j];
667 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
668 for (j=0; j<3; j++) q2[j] += p[j];
669 for (j=0; j<3; j++) q3[j] = (dRandReal()-0.5)*0.99*s[j];
670 dMultiply0 (q4,dGeomGetRotation(box),q3,3,3,1);
671 for (j=0; j<3; j++) q4[j] += p[j];
672 for (j=0; j<3; j++) n[j] = q4[j] - q2[j];
673 dNormalize3 (n);
674 dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]);
675 dGeomRaySetLength (ray,dDISTANCE(q2,q4));
676 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
677
678 // ********** test finite length ray totally outside the box
679
680 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
681 i = dRandInt (3);
682 if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
683 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
684 for (j=0; j<3; j++) q3[j] = q2[j] + p[j];
685 dNormalize3 (q2);
686 dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]);
687 dGeomRaySetLength (ray,10);
688 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
689
690 // ********** test ray from outside to just above surface
691
692 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
693 i = dRandInt (3);
694 if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
695 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
696 for (j=0; j<3; j++) q3[j] = 2*q2[j] + p[j];
697 k = dSqrt(q2[0]*q2[0] + q2[1]*q2[1] + q2[2]*q2[2]);
698 for (j=0; j<3; j++) q2[j] = -q2[j];
699 dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]);
700 dGeomRaySetLength (ray,k*0.99);
701 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
702
703 // ********** test ray from outside to just below surface
704
705 dGeomRaySetLength (ray,k*1.01);
706 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
707
708 // ********** test contact point position for random rays
709
710 for (j=0; j<3; j++) q[j] = dRandReal()*s[j];
711 dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
712 for (j=0; j<3; j++) q2[j] += p[j];
713 for (j=0; j<3; j++) q3[j] = dRandReal()-0.5;
714 dNormalize3 (q3);
715 dGeomRaySet (ray,q2[0],q2[1],q2[2],q3[0],q3[1],q3[2]);
716 dGeomRaySetLength (ray,10);
717 if (dCollide (ray,box,1,&contact,sizeof(dContactGeom))) {
718 // check depth of contact point
719 if (dFabs (dGeomBoxPointDepth
720 (box,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
721 FAILED();
722 // check position of contact point
723 for (j=0; j<3; j++) contact.pos[j] -= p[j];
724 dMultiply1 (q,dGeomGetRotation(box),contact.pos,3,3,1);
725 if ( dFabs(dFabs (q[0]) - 0.5*s[0]) > tol &&
726 dFabs(dFabs (q[1]) - 0.5*s[1]) > tol &&
727 dFabs(dFabs (q[2]) - 0.5*s[2]) > tol) {
728 FAILED();
729 }
730 // also check normal signs
731 if (dDOT (q3,contact.normal) > 0) FAILED();
732
733 draw_all_objects (space);
734 }
735
736 PASSED();
737}
738
739
740int test_ray_and_ccylinder()
741{
742 int j;
743 dContactGeom contact;
744 dVector3 p,a,b,n;
745 dMatrix3 R;
746 dReal r,l,k,x,y;
747
748 dSimpleSpace space(0);
749 dGeomID ray = dCreateRay (0,0);
750 dGeomID ccyl = dCreateCapsule (0,1,1);
751 dSpaceAdd (space,ray);
752 dSpaceAdd (space,ccyl);
753
754 // ********** make a random capped cylinder
755
756 r = dRandReal()*0.5 + 0.01;
757 l = dRandReal()*1 + 0.01;
758 dGeomCapsuleSetParams (ccyl,r,l);
759 dMakeRandomVector (p,3,1.0);
760 dGeomSetPosition (ccyl,p[0],p[1],p[2]);
761 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
762 dRandReal()*2-1,dRandReal()*10-5);
763 dGeomSetRotation (ccyl,R);
764
765 // ********** test ray completely within ccyl
766
767 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
768 dNormalize3 (a);
769 k = (dRandReal()-0.5)*l;
770 for (j=0; j<3; j++) a[j] = p[j] + r*0.99*a[j] + k*0.99*R[j*4+2];
771 for (j=0; j<3; j++) b[j] = dRandReal()-0.5;
772 dNormalize3 (b);
773 k = (dRandReal()-0.5)*l;
774 for (j=0; j<3; j++) b[j] = p[j] + r*0.99*b[j] + k*0.99*R[j*4+2];
775 dGeomRaySetLength (ray,dDISTANCE(a,b));
776 for (j=0; j<3; j++) b[j] -= a[j];
777 dNormalize3 (b);
778 dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
779 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
780
781 // ********** test ray outside ccyl that just misses (between caps)
782
783 k = dRandReal()*2*M_PI;
784 x = sin(k);
785 y = cos(k);
786 for (j=0; j<3; j++) a[j] = x*R[j*4+0] + y*R[j*4+1];
787 k = (dRandReal()-0.5)*l;
788 for (j=0; j<3; j++) b[j] = -a[j]*r*2 + k*R[j*4+2] + p[j];
789 dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]);
790 dGeomRaySetLength (ray,r*0.99);
791 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
792
793 // ********** test ray outside ccyl that just hits (between caps)
794
795 dGeomRaySetLength (ray,r*1.01);
796 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
797 // check depth of contact point
798 if (dFabs (dGeomCapsulePointDepth
799 (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
800 FAILED();
801
802 // ********** test ray outside ccyl that just misses (caps)
803
804 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
805 dNormalize3 (a);
806 if (dDOT14(a,R+2) < 0) {
807 for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r + l*0.5*R[j*4+2];
808 }
809 else {
810 for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r - l*0.5*R[j*4+2];
811 }
812 dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]);
813 dGeomRaySetLength (ray,r*0.99);
814 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
815
816 // ********** test ray outside ccyl that just hits (caps)
817
818 dGeomRaySetLength (ray,r*1.01);
819 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
820 // check depth of contact point
821 if (dFabs (dGeomCapsulePointDepth
822 (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
823 FAILED();
824
825 // ********** test random rays
826
827 for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
828 for (j=0; j<3; j++) n[j] = dRandReal()-0.5;
829 dNormalize3 (n);
830 dGeomRaySet (ray,a[0],a[1],a[2],n[0],n[1],n[2]);
831 dGeomRaySetLength (ray,10);
832
833 if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom))) {
834 // check depth of contact point
835 if (dFabs (dGeomCapsulePointDepth
836 (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
837 FAILED();
838
839 // check normal signs
840 if (dDOT (n,contact.normal) > 0) FAILED();
841
842 draw_all_objects (space);
843 }
844
845 PASSED();
846}
847
848
849int test_ray_and_plane()
850{
851 int j;
852 dContactGeom contact;
853 dVector3 n,p,q,a,b,g,h; // n,d = plane parameters
854 dMatrix3 R;
855 dReal d;
856
857 dSimpleSpace space(0);
858 dGeomID ray = dCreateRay (0,0);
859 dGeomID plane = dCreatePlane (0,0,0,1,0);
860 dSpaceAdd (space,ray);
861 dSpaceAdd (space,plane);
862
863 // ********** make a random plane
864
865 for (j=0; j<3; j++) n[j] = dRandReal() - 0.5;
866 dNormalize3 (n);
867 d = dRandReal() - 0.5;
868 dGeomPlaneSetParams (plane,n[0],n[1],n[2],d);
869 dPlaneSpace (n,p,q);
870
871 // ********** test finite length ray below plane
872
873 dGeomRaySetLength (ray,0.09);
874 a[0] = dRandReal()-0.5;
875 a[1] = dRandReal()-0.5;
876 a[2] = -dRandReal()*0.5 - 0.1;
877 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
878 dGeomSetPosition (ray,b[0],b[1],b[2]);
879 dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
880 dRandReal()*2-1,dRandReal()*10-5);
881 dGeomSetRotation (ray,R);
882 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
883
884 // ********** test finite length ray above plane
885
886 a[0] = dRandReal()-0.5;
887 a[1] = dRandReal()-0.5;
888 a[2] = dRandReal()*0.5 + 0.01;
889 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
890 g[0] = dRandReal()-0.5;
891 g[1] = dRandReal()-0.5;
892 g[2] = dRandReal() + 0.01;
893 for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j];
894 dNormalize3 (h);
895 dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
896 dGeomRaySetLength (ray,10);
897 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
898
899 // ********** test finite length ray that intersects plane
900
901 a[0] = dRandReal()-0.5;
902 a[1] = dRandReal()-0.5;
903 a[2] = dRandReal()-0.5;
904 for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
905 g[0] = dRandReal()-0.5;
906 g[1] = dRandReal()-0.5;
907 g[2] = dRandReal()-0.5;
908 for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j];
909 dNormalize3 (h);
910 dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
911 dGeomRaySetLength (ray,10);
912 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom))) {
913 // test that contact is on plane surface
914 if (dFabs (dDOT(contact.pos,n) - d) > tol) FAILED();
915 // also check normal signs
916 if (dDOT (h,contact.normal) > 0) FAILED();
917 // also check contact point depth
918 if (dFabs (dGeomPlanePointDepth
919 (plane,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
920 FAILED();
921
922 draw_all_objects (space);
923 }
924
925 // ********** test ray that just misses
926
927 for (j=0; j<3; j++) b[j] = (1+d)*n[j];
928 for (j=0; j<3; j++) h[j] = -n[j];
929 dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
930 dGeomRaySetLength (ray,0.99);
931 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
932
933 // ********** test ray that just hits
934
935 dGeomRaySetLength (ray,1.01);
936 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
937
938 // ********** test polarity with typical ground plane
939
940 dGeomPlaneSetParams (plane,0,0,1,0);
941 for (j=0; j<3; j++) a[j] = 0.1;
942 for (j=0; j<3; j++) b[j] = 0;
943 a[2] = 1;
944 b[2] = -1;
945 dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
946 dGeomRaySetLength (ray,2);
947 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
948 if (dFabs (contact.depth - 1) > tol) FAILED();
949 a[2] = -1;
950 b[2] = 1;
951 dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
952 if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
953 if (dFabs (contact.depth - 1) > tol) FAILED();
954
955 PASSED();
956}
957
958//****************************************************************************
959// a really inefficient, but hopefully correct implementation of
960// dBoxTouchesBox(), that does 144 edge-face tests.
961
962// return 1 if edge v1 -> v2 hits the rectangle described by p1,p2,p3
963
964static int edgeIntersectsRect (dVector3 v1, dVector3 v2,
965 dVector3 p1, dVector3 p2, dVector3 p3)
966{
967 int k;
968 dVector3 u1,u2,n,tmp;
969 for (k=0; k<3; k++) u1[k] = p3[k]-p1[k];
970 for (k=0; k<3; k++) u2[k] = p2[k]-p1[k];
971 dReal d1 = dSqrt(dDOT(u1,u1));
972 dReal d2 = dSqrt(dDOT(u2,u2));
973 dNormalize3 (u1);
974 dNormalize3 (u2);
975 if (dFabs(dDOT(u1,u2)) > 1e-6) dDebug (0,"bad u1/u2");
976 dCROSS (n,=,u1,u2);
977 for (k=0; k<3; k++) tmp[k] = v2[k]-v1[k];
978 dReal d = -dDOT(n,p1);
979 if (dFabs(dDOT(n,p1)+d) > 1e-8) dDebug (0,"bad n wrt p1");
980 if (dFabs(dDOT(n,p2)+d) > 1e-8) dDebug (0,"bad n wrt p2");
981 if (dFabs(dDOT(n,p3)+d) > 1e-8) dDebug (0,"bad n wrt p3");
982 dReal alpha = -(d+dDOT(n,v1))/dDOT(n,tmp);
983 for (k=0; k<3; k++) tmp[k] = v1[k]+alpha*(v2[k]-v1[k]);
984 if (dFabs(dDOT(n,tmp)+d) > 1e-6) dDebug (0,"bad tmp");
985 if (alpha < 0) return 0;
986 if (alpha > 1) return 0;
987 for (k=0; k<3; k++) tmp[k] -= p1[k];
988 dReal a1 = dDOT(u1,tmp);
989 dReal a2 = dDOT(u2,tmp);
990 if (a1<0 || a2<0 || a1>d1 || a2>d2) return 0;
991 return 1;
992}
993
994
995// return 1 if box 1 is completely inside box 2
996
997static int box1inside2 (const dVector3 p1, const dMatrix3 R1,
998 const dVector3 side1, const dVector3 p2,
999 const dMatrix3 R2, const dVector3 side2)
1000{
1001 for (int i=-1; i<=1; i+=2) {
1002 for (int j=-1; j<=1; j+=2) {
1003 for (int k=-1; k<=1; k+=2) {
1004 dVector3 v,vv;
1005 v[0] = i*0.5*side1[0];
1006 v[1] = j*0.5*side1[1];
1007 v[2] = k*0.5*side1[2];
1008 dMULTIPLY0_331 (vv,R1,v);
1009 vv[0] += p1[0] - p2[0];
1010 vv[1] += p1[1] - p2[1];
1011 vv[2] += p1[2] - p2[2];
1012 for (int axis=0; axis < 3; axis++) {
1013 dReal z = dDOT14(vv,R2+axis);
1014 if (z < (-side2[axis]*0.5) || z > (side2[axis]*0.5)) return 0;
1015 }
1016 }
1017 }
1018 }
1019 return 1;
1020}
1021
1022
1023// test if any edge from box 1 hits a face from box 2
1024
1025static int testBoxesTouch2 (const dVector3 p1, const dMatrix3 R1,
1026 const dVector3 side1, const dVector3 p2,
1027 const dMatrix3 R2, const dVector3 side2)
1028{
1029 int j,k,j1,j2;
1030
1031 // for 6 faces from box 2
1032 for (int fd=0; fd<3; fd++) { // direction for face
1033
1034 for (int fo=0; fo<2; fo++) { // offset of face
1035 // get four points on the face. first get 2 indexes that are not fd
1036 int k1=0,k2=0;
1037 if (fd==0) { k1 = 1; k2 = 2; }
1038 if (fd==1) { k1 = 0; k2 = 2; }
1039 if (fd==2) { k1 = 0; k2 = 1; }
1040 dVector3 fp[4],tmp;
1041 k=0;
1042 for (j1=-1; j1<=1; j1+=2) {
1043 for (j2=-1; j2<=1; j2+=2) {
1044 fp[k][k1] = j1;
1045 fp[k][k2] = j2;
1046 fp[k][fd] = fo*2-1;
1047 k++;
1048 }
1049 }
1050 for (j=0; j<4; j++) {
1051 for (k=0; k<3; k++) fp[j][k] *= 0.5*side2[k];
1052 dMULTIPLY0_331 (tmp,R2,fp[j]);
1053 for (k=0; k<3; k++) fp[j][k] = tmp[k] + p2[k];
1054 }
1055
1056 // for 8 vertices
1057 dReal v1[3];
1058 for (v1[0]=-1; v1[0] <= 1; v1[0] += 2) {
1059 for (v1[1]=-1; v1[1] <= 1; v1[1] += 2) {
1060 for (v1[2]=-1; v1[2] <= 1; v1[2] += 2) {
1061 // for all possible +ve leading edges from those vertices
1062 for (int ei=0; ei < 3; ei ++) {
1063 if (v1[ei] < 0) {
1064 // get vertex1 -> vertex2 = an edge from box 1
1065 dVector3 vv1,vv2;
1066 for (k=0; k<3; k++) vv1[k] = v1[k] * 0.5*side1[k];
1067 for (k=0; k<3; k++) vv2[k] = (v1[k] + (k==ei)*2)*0.5*side1[k];
1068 dVector3 vertex1,vertex2;
1069 dMULTIPLY0_331 (vertex1,R1,vv1);
1070 dMULTIPLY0_331 (vertex2,R1,vv2);
1071 for (k=0; k<3; k++) vertex1[k] += p1[k];
1072 for (k=0; k<3; k++) vertex2[k] += p1[k];
1073
1074 // see if vertex1 -> vertex2 interesects face
1075 if (edgeIntersectsRect (vertex1,vertex2,fp[0],fp[1],fp[2]))
1076 return 1;
1077 }
1078 }
1079 }
1080 }
1081 }
1082 }
1083 }
1084
1085 if (box1inside2 (p1,R1,side1,p2,R2,side2)) return 1;
1086 if (box1inside2 (p2,R2,side2,p1,R1,side1)) return 1;
1087
1088 return 0;
1089}
1090
1091//****************************************************************************
1092// dBoxTouchesBox() test
1093
1094int test_dBoxTouchesBox()
1095{
1096 int k,bt1,bt2;
1097 dVector3 p1,p2,side1,side2;
1098 dMatrix3 R1,R2;
1099
1100 dSimpleSpace space(0);
1101 dGeomID box1 = dCreateBox (0,1,1,1);
1102 dSpaceAdd (space,box1);
1103 dGeomID box2 = dCreateBox (0,1,1,1);
1104 dSpaceAdd (space,box2);
1105
1106 dMakeRandomVector (p1,3,0.5);
1107 dMakeRandomVector (p2,3,0.5);
1108 for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01;
1109 for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01;
1110 dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1111 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1112 dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1113 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1114
1115 dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]);
1116 dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]);
1117 dGeomSetPosition (box1,p1[0],p1[1],p1[2]);
1118 dGeomSetRotation (box1,R1);
1119 dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
1120 dGeomSetRotation (box2,R2);
1121 draw_all_objects (space);
1122
1123 int t1 = testBoxesTouch2 (p1,R1,side1,p2,R2,side2);
1124 int t2 = testBoxesTouch2 (p2,R2,side2,p1,R1,side1);
1125 bt1 = t1 || t2;
1126 bt2 = dBoxTouchesBox (p1,R1,side1,p2,R2,side2);
1127
1128 if (bt1 != bt2) FAILED();
1129
1130 /*
1131 // some more debugging info if necessary
1132 if (bt1 && bt2) printf ("agree - boxes touch\n");
1133 if (!bt1 && !bt2) printf ("agree - boxes don't touch\n");
1134 if (bt1 && !bt2) printf ("disagree - boxes touch but dBoxTouchesBox "
1135 "says no\n");
1136 if (!bt1 && bt2) printf ("disagree - boxes don't touch but dBoxTouchesBox "
1137 "says yes\n");
1138 */
1139
1140 PASSED();
1141}
1142
1143//****************************************************************************
1144// test box-box collision
1145
1146int test_dBoxBox()
1147{
1148 int k,bt;
1149 dVector3 p1,p2,side1,side2,normal,normal2;
1150 dMatrix3 R1,R2;
1151 dReal depth,depth2;
1152 int code;
1153 dContactGeom contact[48];
1154
1155 dSimpleSpace space(0);
1156 dGeomID box1 = dCreateBox (0,1,1,1);
1157 dSpaceAdd (space,box1);
1158 dGeomID box2 = dCreateBox (0,1,1,1);
1159 dSpaceAdd (space,box2);
1160
1161 dMakeRandomVector (p1,3,0.5);
1162 dMakeRandomVector (p2,3,0.5);
1163 for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01;
1164 for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01;
1165
1166 dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1167 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1168 dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1169 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1170
1171 // dRSetIdentity (R1); // we can also try this
1172 // dRSetIdentity (R2);
1173
1174 dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]);
1175 dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]);
1176 dGeomSetPosition (box1,p1[0],p1[1],p1[2]);
1177 dGeomSetRotation (box1,R1);
1178 dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
1179 dGeomSetRotation (box2,R2);
1180
1181 code = 0;
1182 depth = 0;
1183 bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal,&depth,&code,8,contact,
1184 sizeof(dContactGeom));
1185 if (bt==1) {
1186 p2[0] += normal[0] * 0.96 * depth;
1187 p2[1] += normal[1] * 0.96 * depth;
1188 p2[2] += normal[2] * 0.96 * depth;
1189 bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact,
1190 sizeof(dContactGeom));
1191
1192 /*
1193 dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
1194 draw_all_objects (space);
1195 */
1196
1197 if (bt != 1) {
1198 FAILED();
1199 dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
1200 draw_all_objects (space);
1201 }
1202
1203 p2[0] += normal[0] * 0.08 * depth;
1204 p2[1] += normal[1] * 0.08 * depth;
1205 p2[2] += normal[2] * 0.08 * depth;
1206 bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact,
1207 sizeof(dContactGeom));
1208 if (bt != 0) FAILED();
1209
1210 // dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
1211 // draw_all_objects (space);
1212 }
1213
1214 // printf ("code=%2d depth=%.4f ",code,depth);
1215
1216 PASSED();
1217}
1218
1219//****************************************************************************
1220// graphics
1221
1222int space_pressed = 0;
1223
1224
1225// start simulation - set viewpoint
1226
1227static void start()
1228{
1229 static float xyz[3] = {2.4807,-1.8023,2.7600};
1230 static float hpr[3] = {141.5000,-18.5000,0.0000};
1231 dsSetViewpoint (xyz,hpr);
1232}
1233
1234
1235// called when a key pressed
1236
1237static void command (int cmd)
1238{
1239 if (cmd == ' ') space_pressed = 1;
1240}
1241
1242
1243// simulation loop
1244
1245static void simLoop (int pause)
1246{
1247 do {
1248 draw_all_objects_called = 0;
1249 unsigned long seed = dRandGetSeed();
1250 testslot[graphical_test].test_fn();
1251 if (draw_all_objects_called) {
1252 if (space_pressed) space_pressed = 0; else dRandSetSeed (seed);
1253 }
1254 }
1255 while (!draw_all_objects_called);
1256}
1257
1258//****************************************************************************
1259// do all the tests
1260
1261void do_tests (int argc, char **argv)
1262{
1263 int i,j;
1264
1265 // process command line arguments
1266 if (argc >= 2) {
1267 graphical_test = atoi (argv[1]);
1268 }
1269
1270 if (graphical_test) {
1271 // do one test gaphically and interactively
1272
1273 if (graphical_test < 1 || graphical_test >= MAX_TESTS ||
1274 !testslot[graphical_test].name) {
1275 dError (0,"invalid test number");
1276 }
1277
1278 printf ("performing test: %s\n",testslot[graphical_test].name);
1279
1280 // setup pointers to drawstuff callback functions
1281 dsFunctions fn;
1282 fn.version = DS_VERSION;
1283 fn.start = &start;
1284 fn.step = &simLoop;
1285 fn.command = &command;
1286 fn.stop = 0;
1287 fn.path_to_textures = "../../drawstuff/textures";
1288
1289 dsSetSphereQuality (3);
1290 dsSetCapsuleQuality (8);
1291 dsSimulationLoop (argc,argv,1280,900,&fn);
1292 }
1293 else {
1294 // do all tests noninteractively
1295
1296 for (i=0; i<MAX_TESTS; i++) testslot[i].number = i;
1297
1298 // first put the active tests into a separate array
1299 int n=0;
1300 for (i=0; i<MAX_TESTS; i++) if (testslot[i].name) n++;
1301 TestSlot **ts = (TestSlot**) alloca (n * sizeof(TestSlot*));
1302 j = 0;
1303 for (i=0; i<MAX_TESTS; i++) if (testslot[i].name) ts[j++] = testslot+i;
1304 if (j != n) dDebug (0,"internal");
1305
1306 // do two test batches. the first test batch has far fewer reps and will
1307 // catch problems quickly. if all tests in the first batch passes, the
1308 // second batch is run.
1309
1310 for (i=0; i<n; i++) ts[i]->failcount = 0;
1311 int total_reps=0;
1312 for (int batch=0; batch<2; batch++) {
1313 int reps = (batch==0) ? TEST_REPS1 : TEST_REPS2;
1314 total_reps += reps;
1315 printf ("testing batch %d (%d reps)...\n",batch+1,reps);
1316
1317 // run tests
1318 for (j=0; j<reps; j++) {
1319 for (i=0; i<n; i++) {
1320 current_test = ts[i]->number;
1321 if (ts[i]->test_fn() != 1) ts[i]->failcount++;
1322 }
1323 }
1324
1325 // check for failures
1326 int total_fail_count=0;
1327 for (i=0; i<n; i++) total_fail_count += ts[i]->failcount;
1328 if (total_fail_count) break;
1329 }
1330
1331 // print results
1332 for (i=0; i<n; i++) {
1333 printf ("%3d: %-30s: ",ts[i]->number,ts[i]->name);
1334 if (ts[i]->failcount) {
1335 printf ("FAILED (%.2f%%) at line %d\n",
1336 double(ts[i]->failcount)/double(total_reps)*100.0,
1337 ts[i]->last_failed_line);
1338 }
1339 else {
1340 printf ("ok\n");
1341 }
1342 }
1343 }
1344}
1345
1346//****************************************************************************
1347
1348int main (int argc, char **argv)
1349{
1350 // setup all tests
1351
1352 memset (testslot,0,sizeof(testslot));
1353 dInitODE();
1354
1355 MAKE_TEST(1,test_sphere_point_depth);
1356 MAKE_TEST(2,test_box_point_depth);
1357 MAKE_TEST(3,test_ccylinder_point_depth);
1358 MAKE_TEST(4,test_plane_point_depth);
1359
1360 MAKE_TEST(10,test_ray_and_sphere);
1361 MAKE_TEST(11,test_ray_and_box);
1362 MAKE_TEST(12,test_ray_and_ccylinder);
1363 MAKE_TEST(13,test_ray_and_plane);
1364
1365 MAKE_TEST(100,test_dBoxTouchesBox);
1366 MAKE_TEST(101,test_dBoxBox);
1367
1368 do_tests (argc,argv);
1369 dCloseODE();
1370 return 0;
1371}
diff --git a/libraries/ode-0.9/ode/demo/demo_convex_cd.cpp b/libraries/ode-0.9/ode/demo/demo_convex_cd.cpp
deleted file mode 100644
index e1764f3..0000000
--- a/libraries/ode-0.9/ode/demo/demo_convex_cd.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <stdio.h>
24#include <math.h>
25#include <ode/ode.h>
26#include <drawstuff/drawstuff.h>
27#ifdef _MSC_VER
28#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
29#endif
30
31
32#ifndef M_PI
33#define M_PI (3.14159265358979323846)
34#endif
35
36//<---- Convex Object
37dReal planes[]= // planes for a cube
38 {
39 1.0f ,0.0f ,0.0f ,0.25f,
40 0.0f ,1.0f ,0.0f ,0.25f,
41 0.0f ,0.0f ,1.0f ,0.25f,
42 -1.0f,0.0f ,0.0f ,0.25f,
43 0.0f ,-1.0f,0.0f ,0.25f,
44 0.0f ,0.0f ,-1.0f,0.25f
45 /*
46 1.0f ,0.0f ,0.0f ,2.0f,
47 0.0f ,1.0f ,0.0f ,1.0f,
48 0.0f ,0.0f ,1.0f ,1.0f,
49 0.0f ,0.0f ,-1.0f,1.0f,
50 0.0f ,-1.0f,0.0f ,1.0f,
51 -1.0f,0.0f ,0.0f ,0.0f
52 */
53 };
54const unsigned int planecount=6;
55
56dReal points[]= // points for a cube
57 {
58 0.25f,0.25f,0.25f, // point 0
59 -0.25f,0.25f,0.25f, // point 1
60
61 0.25f,-0.25f,0.25f, // point 2
62 -0.25f,-0.25f,0.25f,// point 3
63
64 0.25f,0.25f,-0.25f, // point 4
65 -0.25f,0.25f,-0.25f,// point 5
66
67 0.25f,-0.25f,-0.25f,// point 6
68 -0.25f,-0.25f,-0.25f,// point 7
69 };
70const unsigned int pointcount=8;
71unsigned int polygons[] = //Polygons for a cube (6 squares)
72 {
73 4,0,2,6,4, // positive X
74 4,1,0,4,5, // positive Y
75 4,0,1,3,2, // positive Z
76 4,3,1,5,7, // negative X
77 4,2,3,7,6, // negative Y
78 4,5,4,6,7, // negative Z
79 };
80//----> Convex Object
81
82#ifdef dDOUBLE
83#define dsDrawConvex dsDrawConvexD
84#define dsDrawBox dsDrawBoxD
85#endif
86
87dGeomID geoms[2];
88dSpaceID space;
89dWorldID world;
90dJointGroupID contactgroup;
91
92void start()
93{
94 // adjust the starting viewpoint a bit
95 float xyz[3],hpr[3];
96 dsGetViewpoint (xyz,hpr);
97 hpr[0] += 7;
98 dsSetViewpoint (xyz,hpr);
99 geoms[0]=dCreateConvex (space,
100 planes,
101 planecount,
102 points,
103 pointcount,
104 polygons);
105 dGeomSetPosition (geoms[0],0,0,0.25);
106 geoms[1]=dCreateConvex (space,
107 planes,
108 planecount,
109 points,
110 pointcount,
111 polygons);
112 dGeomSetPosition (geoms[1],0.25,0.25,0.70);
113
114}
115
116int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
117 dContactGeom *contact, int skip);
118void simLoop (int pause)
119{
120 static bool DumpInfo=true;
121 const dReal ss[3] = {0.02,0.02,0.02};
122 dContactGeom contacts[8];
123 int contactcount = dCollideConvexConvex(geoms[0],geoms[1],8,contacts,sizeof(dContactGeom));
124 //fprintf(stdout,"Contact Count %d\n",contactcount);
125 const dReal* pos;
126 const dReal* R;
127 dsSetTexture (DS_WOOD);
128 pos = dGeomGetPosition (geoms[0]);
129 R = dGeomGetRotation (geoms[0]);
130 dsSetColor (0.6f,0.6f,1);
131 dsDrawConvex(pos,R,planes,
132 planecount,
133 points,
134 pointcount,
135 polygons);
136 pos = dGeomGetPosition (geoms[1]);
137 R = dGeomGetRotation (geoms[1]);
138 dsSetColor (0.4f,1,1);
139 dsDrawConvex(pos,R,planes,
140 planecount,
141 points,
142 pointcount,
143 polygons);
144 /*if (show_contacts) */
145 dMatrix3 RI;
146 dRSetIdentity (RI);
147 dsSetColor (1.0f,0,0);
148 for(int i=0;i<contactcount;++i)
149 {
150 if(DumpInfo)
151 {
152 //DumpInfo=false;
153 fprintf(stdout,"Contact %d Normal %f,%f,%f Depth %f\n",
154 i,
155 contacts[i].normal[0],
156 contacts[i].normal[1],
157 contacts[i].normal[2],
158 contacts[i].depth);
159 }
160 dsDrawBox (contacts[i].pos,RI,ss);
161 }
162 if(DumpInfo)
163 DumpInfo=false;
164
165}
166
167
168void command (int cmd)
169{
170 dsPrint ("received command %d (`%c')\n",cmd,cmd);
171}
172
173
174int main (int argc, char **argv)
175{
176 // setup pointers to callback functions
177 dsFunctions fn;
178 fn.version = DS_VERSION;
179 fn.start = &start;
180 fn.step = &simLoop;
181 fn.command = command;
182 fn.stop = 0;
183 fn.path_to_textures = "../../drawstuff/textures"; // uses default
184 world = dWorldCreate();
185 space = dHashSpaceCreate (0);
186 contactgroup = dJointGroupCreate (0);
187
188 // run simulation
189 dsSimulationLoop (argc,argv,400,400,&fn);
190 dJointGroupDestroy (contactgroup);
191 dSpaceDestroy (space);
192 dWorldDestroy (world);
193
194 return 0;
195}
diff --git a/libraries/ode-0.9/ode/demo/demo_crash.cpp b/libraries/ode-0.9/ode/demo/demo_crash.cpp
deleted file mode 100644
index 29ec01f..0000000
--- a/libraries/ode-0.9/ode/demo/demo_crash.cpp
+++ /dev/null
@@ -1,635 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// This is a demo of the QuickStep and StepFast methods,
24// originally by David Whittaker.
25
26#include <ode/ode.h>
27#include <drawstuff/drawstuff.h>
28
29#ifdef _MSC_VER
30#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
31#endif
32
33// select correct drawing functions
34
35#ifdef dDOUBLE
36#define dsDrawBox dsDrawBoxD
37#define dsDrawSphere dsDrawSphereD
38#define dsDrawCylinder dsDrawCylinderD
39#define dsDrawCapsule dsDrawCapsuleD
40#endif
41
42
43// select the method you want to test here (only uncomment *one* line)
44#define QUICKSTEP 1
45//#define STEPFAST 1
46
47// some constants
48
49#define LENGTH 3.5 // chassis length
50#define WIDTH 2.5 // chassis width
51#define HEIGHT 1.0 // chassis height
52#define RADIUS 0.5 // wheel radius
53#define STARTZ 1.0 // starting height of chassis
54#define CMASS 1 // chassis mass
55#define WMASS 1 // wheel mass
56#define COMOFFSET -5 // center of mass offset
57#define WALLMASS 1 // wall box mass
58#define BALLMASS 1 // ball mass
59#define FMAX 25 // car engine fmax
60#define ROWS 1 // rows of cars
61#define COLS 1 // columns of cars
62#define ITERS 20 // number of iterations
63#define WBOXSIZE 1.0 // size of wall boxes
64#define WALLWIDTH 12 // width of wall
65#define WALLHEIGHT 10 // height of wall
66#define DISABLE_THRESHOLD 0.008 // maximum velocity (squared) a body can have and be disabled
67#define DISABLE_STEPS 10 // number of steps a box has to have been disable-able before it will be disabled
68#define CANNON_X -10 // x position of cannon
69#define CANNON_Y 5 // y position of cannon
70#define CANNON_BALL_MASS 10 // mass of the cannon ball
71#define CANNON_BALL_RADIUS 0.5
72
73//#define BOX
74#define CARS
75#define WALL
76//#define BALLS
77//#define BALLSTACK
78//#define ONEBALL
79//#define CENTIPEDE
80#define CANNON
81
82// dynamics and collision objects (chassis, 3 wheels, environment)
83
84static dWorldID world;
85static dSpaceID space;
86static dBodyID body[10000];
87static int bodies;
88static dJointID joint[100000];
89static int joints;
90static dJointGroupID contactgroup;
91static dGeomID ground;
92static dGeomID box[10000];
93static int boxes;
94static dGeomID sphere[10000];
95static int spheres;
96static dGeomID wall_boxes[10000];
97static dBodyID wall_bodies[10000];
98static dGeomID cannon_ball_geom;
99static dBodyID cannon_ball_body;
100static int wb_stepsdis[10000];
101static int wb;
102static bool doFast;
103static dBodyID b;
104static dMass m;
105
106
107// things that the user controls
108
109static dReal turn = 0, speed = 0; // user commands
110static dReal cannon_angle=0,cannon_elevation=-1.2;
111
112
113
114// this is called by dSpaceCollide when two objects in space are
115// potentially colliding.
116
117static void nearCallback (void *data, dGeomID o1, dGeomID o2)
118{
119 int i,n;
120
121 dBodyID b1 = dGeomGetBody(o1);
122 dBodyID b2 = dGeomGetBody(o2);
123 if (b1 && b2 && dAreConnected(b1, b2))
124 return;
125
126 const int N = 4;
127 dContact contact[N];
128 n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
129 if (n > 0) {
130 for (i=0; i<n; i++) {
131 contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1;
132 if (dGeomGetClass(o1) == dSphereClass || dGeomGetClass(o2) == dSphereClass)
133 contact[i].surface.mu = 20;
134 else
135 contact[i].surface.mu = 0.5;
136 contact[i].surface.slip1 = 0.0;
137 contact[i].surface.slip2 = 0.0;
138 contact[i].surface.soft_erp = 0.8;
139 contact[i].surface.soft_cfm = 0.01;
140 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
141 dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
142 }
143 }
144}
145
146
147// start simulation - set viewpoint
148
149static void start()
150{
151 static float xyz[3] = {3.8548f,9.0843f,7.5900f};
152 static float hpr[3] = {-145.5f,-22.5f,0.25f};
153 dsSetViewpoint (xyz,hpr);
154 printf ("Press:\t'a' to increase speed.\n"
155 "\t'z' to decrease speed.\n"
156 "\t',' to steer left.\n"
157 "\t'.' to steer right.\n"
158 "\t' ' to reset speed and steering.\n"
159 "\t'[' to turn the cannon left.\n"
160 "\t']' to turn the cannon right.\n"
161 "\t'1' to raise the cannon.\n"
162 "\t'2' to lower the cannon.\n"
163 "\t'x' to shoot from the cannon.\n"
164 "\t'f' to toggle fast step mode.\n"
165 "\t'+' to increase AutoEnableDepth.\n"
166 "\t'-' to decrease AutoEnableDepth.\n"
167 "\t'r' to reset simulation.\n");
168}
169
170
171void makeCar(dReal x, dReal y, int &bodyI, int &jointI, int &boxI, int &sphereI)
172{
173 int i;
174 dMass m;
175
176 // chassis body
177 body[bodyI] = dBodyCreate (world);
178 dBodySetPosition (body[bodyI],x,y,STARTZ);
179 dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
180 dMassAdjust (&m,CMASS/2.0);
181 dBodySetMass (body[bodyI],&m);
182 box[boxI] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
183 dGeomSetBody (box[boxI],body[bodyI]);
184
185 // wheel bodies
186 for (i=1; i<=4; i++) {
187 body[bodyI+i] = dBodyCreate (world);
188 dQuaternion q;
189 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
190 dBodySetQuaternion (body[bodyI+i],q);
191 dMassSetSphere (&m,1,RADIUS);
192 dMassAdjust (&m,WMASS);
193 dBodySetMass (body[bodyI+i],&m);
194 sphere[sphereI+i-1] = dCreateSphere (space,RADIUS);
195 dGeomSetBody (sphere[sphereI+i-1],body[bodyI+i]);
196 }
197 dBodySetPosition (body[bodyI+1],x+0.4*LENGTH-0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
198 dBodySetPosition (body[bodyI+2],x+0.4*LENGTH-0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
199 dBodySetPosition (body[bodyI+3],x-0.4*LENGTH+0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
200 dBodySetPosition (body[bodyI+4],x-0.4*LENGTH+0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
201
202 // front and back wheel hinges
203 for (i=0; i<4; i++) {
204 joint[jointI+i] = dJointCreateHinge2 (world,0);
205 dJointAttach (joint[jointI+i],body[bodyI],body[bodyI+i+1]);
206 const dReal *a = dBodyGetPosition (body[bodyI+i+1]);
207 dJointSetHinge2Anchor (joint[jointI+i],a[0],a[1],a[2]);
208 dJointSetHinge2Axis1 (joint[jointI+i],0,0,(i<2 ? 1 : -1));
209 dJointSetHinge2Axis2 (joint[jointI+i],0,1,0);
210 dJointSetHinge2Param (joint[jointI+i],dParamSuspensionERP,0.8);
211 dJointSetHinge2Param (joint[jointI+i],dParamSuspensionCFM,1e-5);
212 dJointSetHinge2Param (joint[jointI+i],dParamVel2,0);
213 dJointSetHinge2Param (joint[jointI+i],dParamFMax2,FMAX);
214 }
215
216 //center of mass offset body. (hang another copy of the body COMOFFSET units below it by a fixed joint)
217 dBodyID b = dBodyCreate (world);
218 dBodySetPosition (b,x,y,STARTZ+COMOFFSET);
219 dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
220 dMassAdjust (&m,CMASS/2.0);
221 dBodySetMass (b,&m);
222 dJointID j = dJointCreateFixed(world, 0);
223 dJointAttach(j, body[bodyI], b);
224 dJointSetFixed(j);
225 //box[boxI+1] = dCreateBox(space,LENGTH,WIDTH,HEIGHT);
226 //dGeomSetBody (box[boxI+1],b);
227
228 bodyI += 5;
229 jointI += 4;
230 boxI += 1;
231 sphereI += 4;
232}
233
234
235void resetSimulation()
236{
237 int i;
238 i = 0;
239 // destroy world if it exists
240 if (bodies)
241 {
242 dJointGroupDestroy (contactgroup);
243 dSpaceDestroy (space);
244 dWorldDestroy (world);
245 }
246
247 for (i = 0; i < 1000; i++)
248 wb_stepsdis[i] = 0;
249
250 // recreate world
251
252 world = dWorldCreate();
253 space = dHashSpaceCreate (0);
254 contactgroup = dJointGroupCreate (0);
255 dWorldSetGravity (world,0,0,-1.5);
256 dWorldSetCFM (world, 1e-5);
257 dWorldSetERP (world, 0.8);
258 dWorldSetQuickStepNumIterations (world,ITERS);
259 ground = dCreatePlane (space,0,0,1,0);
260
261 bodies = 0;
262 joints = 0;
263 boxes = 0;
264 spheres = 0;
265 wb = 0;
266
267#ifdef CARS
268 for (dReal x = 0.0; x < COLS*(LENGTH+RADIUS); x += LENGTH+RADIUS)
269 for (dReal y = -((ROWS-1)*(WIDTH/2+RADIUS)); y <= ((ROWS-1)*(WIDTH/2+RADIUS)); y += WIDTH+RADIUS*2)
270 makeCar(x, y, bodies, joints, boxes, spheres);
271#endif
272#ifdef WALL
273 bool offset = false;
274 for (dReal z = WBOXSIZE/2.0; z <= WALLHEIGHT; z+=WBOXSIZE)
275 {
276 offset = !offset;
277 for (dReal y = (-WALLWIDTH+z)/2; y <= (WALLWIDTH-z)/2; y+=WBOXSIZE)
278 {
279 wall_bodies[wb] = dBodyCreate (world);
280 dBodySetPosition (wall_bodies[wb],-20,y,z);
281 dMassSetBox (&m,1,WBOXSIZE,WBOXSIZE,WBOXSIZE);
282 dMassAdjust (&m, WALLMASS);
283 dBodySetMass (wall_bodies[wb],&m);
284 wall_boxes[wb] = dCreateBox (space,WBOXSIZE,WBOXSIZE,WBOXSIZE);
285 dGeomSetBody (wall_boxes[wb],wall_bodies[wb]);
286 //dBodyDisable(wall_bodies[wb++]);
287 wb++;
288 }
289 }
290 dMessage(0,"wall boxes: %i", wb);
291#endif
292#ifdef BALLS
293 for (dReal x = -7; x <= -4; x+=1)
294 for (dReal y = -1.5; y <= 1.5; y+=1)
295 for (dReal z = 1; z <= 4; z+=1)
296 {
297 b = dBodyCreate (world);
298 dBodySetPosition (b,x*RADIUS*2,y*RADIUS*2,z*RADIUS*2);
299 dMassSetSphere (&m,1,RADIUS);
300 dMassAdjust (&m, BALLMASS);
301 dBodySetMass (b,&m);
302 sphere[spheres] = dCreateSphere (space,RADIUS);
303 dGeomSetBody (sphere[spheres++],b);
304 }
305#endif
306#ifdef ONEBALL
307 b = dBodyCreate (world);
308 dBodySetPosition (b,0,0,2);
309 dMassSetSphere (&m,1,RADIUS);
310 dMassAdjust (&m, 1);
311 dBodySetMass (b,&m);
312 sphere[spheres] = dCreateSphere (space,RADIUS);
313 dGeomSetBody (sphere[spheres++],b);
314#endif
315#ifdef BALLSTACK
316 for (dReal z = 1; z <= 6; z+=1)
317 {
318 b = dBodyCreate (world);
319 dBodySetPosition (b,0,0,z*RADIUS*2);
320 dMassSetSphere (&m,1,RADIUS);
321 dMassAdjust (&m, 0.1);
322 dBodySetMass (b,&m);
323 sphere[spheres] = dCreateSphere (space,RADIUS);
324 dGeomSetBody (sphere[spheres++],b);
325 }
326#endif
327#ifdef CENTIPEDE
328 dBodyID lastb = 0;
329 for (dReal y = 0; y < 10*LENGTH; y+=LENGTH+0.1)
330 {
331 // chassis body
332
333 b = body[bodies] = dBodyCreate (world);
334 dBodySetPosition (body[bodies],-15,y,STARTZ);
335 dMassSetBox (&m,1,WIDTH,LENGTH,HEIGHT);
336 dMassAdjust (&m,CMASS);
337 dBodySetMass (body[bodies],&m);
338 box[boxes] = dCreateBox (space,WIDTH,LENGTH,HEIGHT);
339 dGeomSetBody (box[boxes++],body[bodies++]);
340
341 for (dReal x = -17; x > -20; x-=RADIUS*2)
342 {
343 body[bodies] = dBodyCreate (world);
344 dBodySetPosition(body[bodies], x, y, STARTZ);
345 dMassSetSphere(&m, 1, RADIUS);
346 dMassAdjust(&m, WMASS);
347 dBodySetMass(body[bodies], &m);
348 sphere[spheres] = dCreateSphere (space, RADIUS);
349 dGeomSetBody (sphere[spheres++], body[bodies]);
350
351 joint[joints] = dJointCreateHinge2 (world,0);
352 if (x == -17)
353 dJointAttach (joint[joints],b,body[bodies]);
354 else
355 dJointAttach (joint[joints],body[bodies-2],body[bodies]);
356 const dReal *a = dBodyGetPosition (body[bodies++]);
357 dJointSetHinge2Anchor (joint[joints],a[0],a[1],a[2]);
358 dJointSetHinge2Axis1 (joint[joints],0,0,1);
359 dJointSetHinge2Axis2 (joint[joints],1,0,0);
360 dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
361 dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
362 dJointSetHinge2Param (joint[joints],dParamLoStop,0);
363 dJointSetHinge2Param (joint[joints],dParamHiStop,0);
364 dJointSetHinge2Param (joint[joints],dParamVel2,-10.0);
365 dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
366
367 body[bodies] = dBodyCreate (world);
368 dBodySetPosition(body[bodies], -30 - x, y, STARTZ);
369 dMassSetSphere(&m, 1, RADIUS);
370 dMassAdjust(&m, WMASS);
371 dBodySetMass(body[bodies], &m);
372 sphere[spheres] = dCreateSphere (space, RADIUS);
373 dGeomSetBody (sphere[spheres++], body[bodies]);
374
375 joint[joints] = dJointCreateHinge2 (world,0);
376 if (x == -17)
377 dJointAttach (joint[joints],b,body[bodies]);
378 else
379 dJointAttach (joint[joints],body[bodies-2],body[bodies]);
380 const dReal *b = dBodyGetPosition (body[bodies++]);
381 dJointSetHinge2Anchor (joint[joints],b[0],b[1],b[2]);
382 dJointSetHinge2Axis1 (joint[joints],0,0,1);
383 dJointSetHinge2Axis2 (joint[joints],1,0,0);
384 dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
385 dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
386 dJointSetHinge2Param (joint[joints],dParamLoStop,0);
387 dJointSetHinge2Param (joint[joints],dParamHiStop,0);
388 dJointSetHinge2Param (joint[joints],dParamVel2,10.0);
389 dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
390 }
391 if (lastb)
392 {
393 dJointID j = dJointCreateFixed(world,0);
394 dJointAttach (j, b, lastb);
395 dJointSetFixed(j);
396 }
397 lastb = b;
398 }
399#endif
400#ifdef BOX
401 body[bodies] = dBodyCreate (world);
402 dBodySetPosition (body[bodies],0,0,HEIGHT/2);
403 dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
404 dMassAdjust (&m, 1);
405 dBodySetMass (body[bodies],&m);
406 box[boxes] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
407 dGeomSetBody (box[boxes++],body[bodies++]);
408#endif
409#ifdef CANNON
410 cannon_ball_body = dBodyCreate (world);
411 cannon_ball_geom = dCreateSphere (space,CANNON_BALL_RADIUS);
412 dMassSetSphereTotal (&m,CANNON_BALL_MASS,CANNON_BALL_RADIUS);
413 dBodySetMass (cannon_ball_body,&m);
414 dGeomSetBody (cannon_ball_geom,cannon_ball_body);
415 dBodySetPosition (cannon_ball_body,CANNON_X,CANNON_Y,CANNON_BALL_RADIUS);
416#endif
417}
418
419// called when a key pressed
420
421static void command (int cmd)
422{
423 switch (cmd) {
424 case 'a': case 'A':
425 speed += 0.3;
426 break;
427 case 'z': case 'Z':
428 speed -= 0.3;
429 break;
430 case ',':
431 turn += 0.1;
432 if (turn > 0.3)
433 turn = 0.3;
434 break;
435 case '.':
436 turn -= 0.1;
437 if (turn < -0.3)
438 turn = -0.3;
439 break;
440 case ' ':
441 speed = 0;
442 turn = 0;
443 break;
444 case 'f': case 'F':
445 doFast = !doFast;
446 break;
447 case '+':
448 dWorldSetAutoEnableDepthSF1 (world, dWorldGetAutoEnableDepthSF1 (world) + 1);
449 break;
450 case '-':
451 dWorldSetAutoEnableDepthSF1 (world, dWorldGetAutoEnableDepthSF1 (world) - 1);
452 break;
453 case 'r': case 'R':
454 resetSimulation();
455 break;
456 case '[':
457 cannon_angle += 0.1;
458 break;
459 case ']':
460 cannon_angle -= 0.1;
461 break;
462 case '1':
463 cannon_elevation += 0.1;
464 break;
465 case '2':
466 cannon_elevation -= 0.1;
467 break;
468 case 'x': case 'X': {
469 dMatrix3 R2,R3,R4;
470 dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
471 dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
472 dMultiply0 (R4,R2,R3,3,3,3);
473 dReal cpos[3] = {CANNON_X,CANNON_Y,1};
474 for (int i=0; i<3; i++) cpos[i] += 3*R4[i*4+2];
475 dBodySetPosition (cannon_ball_body,cpos[0],cpos[1],cpos[2]);
476 dReal force = 10;
477 dBodySetLinearVel (cannon_ball_body,force*R4[2],force*R4[6],force*R4[10]);
478 dBodySetAngularVel (cannon_ball_body,0,0,0);
479 break;
480 }
481 }
482}
483
484
485// simulation loop
486
487static void simLoop (int pause)
488{
489 int i, j;
490
491 dsSetTexture (DS_WOOD);
492
493 if (!pause) {
494#ifdef BOX
495 dBodyAddForce(body[bodies-1],lspeed,0,0);
496#endif
497 for (j = 0; j < joints; j++)
498 {
499 dReal curturn = dJointGetHinge2Angle1 (joint[j]);
500 //dMessage (0,"curturn %e, turn %e, vel %e", curturn, turn, (turn-curturn)*1.0);
501 dJointSetHinge2Param(joint[j],dParamVel,(turn-curturn)*1.0);
502 dJointSetHinge2Param(joint[j],dParamFMax,dInfinity);
503 dJointSetHinge2Param(joint[j],dParamVel2,speed);
504 dJointSetHinge2Param(joint[j],dParamFMax2,FMAX);
505 dBodyEnable(dJointGetBody(joint[j],0));
506 dBodyEnable(dJointGetBody(joint[j],1));
507 }
508 if (doFast)
509 {
510 dSpaceCollide (space,0,&nearCallback);
511#if defined(QUICKSTEP)
512 dWorldQuickStep (world,0.05);
513#elif defined(STEPFAST)
514 dWorldStepFast1 (world,0.05,ITERS);
515#endif
516 dJointGroupEmpty (contactgroup);
517 }
518 else
519 {
520 dSpaceCollide (space,0,&nearCallback);
521 dWorldStep (world,0.05);
522 dJointGroupEmpty (contactgroup);
523 }
524
525 for (i = 0; i < wb; i++)
526 {
527 b = dGeomGetBody(wall_boxes[i]);
528 if (dBodyIsEnabled(b))
529 {
530 bool disable = true;
531 const dReal *lvel = dBodyGetLinearVel(b);
532 dReal lspeed = lvel[0]*lvel[0]+lvel[1]*lvel[1]+lvel[2]*lvel[2];
533 if (lspeed > DISABLE_THRESHOLD)
534 disable = false;
535 const dReal *avel = dBodyGetAngularVel(b);
536 dReal aspeed = avel[0]*avel[0]+avel[1]*avel[1]+avel[2]*avel[2];
537 if (aspeed > DISABLE_THRESHOLD)
538 disable = false;
539
540 if (disable)
541 wb_stepsdis[i]++;
542 else
543 wb_stepsdis[i] = 0;
544
545 if (wb_stepsdis[i] > DISABLE_STEPS)
546 {
547 dBodyDisable(b);
548 dsSetColor(0.5,0.5,1);
549 }
550 else
551 dsSetColor(1,1,1);
552
553 }
554 else
555 dsSetColor(0.4,0.4,0.4);
556 dVector3 ss;
557 dGeomBoxGetLengths (wall_boxes[i], ss);
558 dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
559 }
560 }
561 else
562 {
563 for (i = 0; i < wb; i++)
564 {
565 b = dGeomGetBody(wall_boxes[i]);
566 if (dBodyIsEnabled(b))
567 dsSetColor(1,1,1);
568 else
569 dsSetColor(0.4,0.4,0.4);
570 dVector3 ss;
571 dGeomBoxGetLengths (wall_boxes[i], ss);
572 dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
573 }
574 }
575
576 dsSetColor (0,1,1);
577 dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
578 for (i = 0; i < boxes; i++)
579 dsDrawBox (dGeomGetPosition(box[i]),dGeomGetRotation(box[i]),sides);
580 dsSetColor (1,1,1);
581 for (i=0; i< spheres; i++) dsDrawSphere (dGeomGetPosition(sphere[i]),
582 dGeomGetRotation(sphere[i]),RADIUS);
583
584 // draw the cannon
585 dsSetColor (1,1,0);
586 dMatrix3 R2,R3,R4;
587 dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
588 dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
589 dMultiply0 (R4,R2,R3,3,3,3);
590 dReal cpos[3] = {CANNON_X,CANNON_Y,1};
591 dReal csides[3] = {2,2,2};
592 dsDrawBox (cpos,R2,csides);
593 for (i=0; i<3; i++) cpos[i] += 1.5*R4[i*4+2];
594 dsDrawCylinder (cpos,R4,3,0.5);
595
596 // draw the cannon ball
597 dsDrawSphere (dBodyGetPosition(cannon_ball_body),dBodyGetRotation(cannon_ball_body),
598 CANNON_BALL_RADIUS);
599}
600
601int main (int argc, char **argv)
602{
603 doFast = true;
604
605 // setup pointers to drawstuff callback functions
606 dsFunctions fn;
607 fn.version = DS_VERSION;
608 fn.start = &start;
609 fn.step = &simLoop;
610 fn.command = &command;
611 fn.stop = 0;
612 fn.path_to_textures = "../../drawstuff/textures";
613 if(argc==2)
614 {
615 fn.path_to_textures = argv[1];
616 }
617
618 dInitODE();
619
620 bodies = 0;
621 joints = 0;
622 boxes = 0;
623 spheres = 0;
624
625 resetSimulation();
626
627 // run simulation
628 dsSimulationLoop (argc,argv,352,288,&fn);
629
630 dJointGroupDestroy (contactgroup);
631 dSpaceDestroy (space);
632 dWorldDestroy (world);
633 dCloseODE();
634 return 0;
635}
diff --git a/libraries/ode-0.9/ode/demo/demo_cyl.cpp b/libraries/ode-0.9/ode/demo/demo_cyl.cpp
deleted file mode 100644
index 3692234..0000000
--- a/libraries/ode-0.9/ode/demo/demo_cyl.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// Test for non-capped cylinder, by Bram Stolk
24#include <ode/config.h>
25#include <assert.h>
26#ifdef HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29#include <ode/ode.h>
30#include <drawstuff/drawstuff.h>
31
32#include "world_geom3.h" // this is our world mesh
33
34#ifdef _MSC_VER
35#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
36#endif
37
38#define BOX
39#define CYL
40
41// some constants
42
43#define RADIUS 0.22 // wheel radius
44#define WMASS 0.2 // wheel mass
45#define WHEELW 0.2 // wheel width
46#define BOXSZ 0.4 // box size
47//#define CYL_GEOM_OFFSET // rotate cylinder using geom offset
48
49// dynamics and collision objects (chassis, 3 wheels, environment)
50
51static dWorldID world;
52static dSpaceID space;
53#ifdef BOX
54static dBodyID boxbody;
55static dGeomID boxgeom;
56#endif
57#ifdef CYL
58static dBodyID cylbody;
59static dGeomID cylgeom;
60#endif
61static dJointGroupID contactgroup;
62static dGeomID world_mesh;
63
64
65// this is called by dSpaceCollide when two objects in space are
66// potentially colliding.
67
68static void nearCallback (void *data, dGeomID o1, dGeomID o2)
69{
70 assert(o1);
71 assert(o2);
72
73 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
74 {
75 fprintf(stderr,"testing space %p %p\n", o1,o2);
76 // colliding a space with something
77 dSpaceCollide2(o1,o2,data,&nearCallback);
78 // Note we do not want to test intersections within a space,
79 // only between spaces.
80 return;
81 }
82
83// fprintf(stderr,"testing geoms %p %p\n", o1, o2);
84
85 const int N = 32;
86 dContact contact[N];
87 int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
88 if (n > 0)
89 {
90 for (int i=0; i<n; i++)
91 {
92 contact[i].surface.slip1 = 0.7;
93 contact[i].surface.slip2 = 0.7;
94 contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
95 contact[i].surface.mu = 50.0; // was: dInfinity
96 contact[i].surface.soft_erp = 0.96;
97 contact[i].surface.soft_cfm = 0.04;
98 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
99 dJointAttach (c,
100 dGeomGetBody(contact[i].geom.g1),
101 dGeomGetBody(contact[i].geom.g2));
102 }
103 }
104}
105
106
107// start simulation - set viewpoint
108
109static void start()
110{
111 static float xyz[3] = {-8,-9,3};
112 static float hpr[3] = {45.0000f,-27.5000f,0.0000f};
113 dsSetViewpoint (xyz,hpr);
114}
115
116
117
118static void reset_state(void)
119{
120 float sx=-4, sy=-4, sz=2;
121 dQuaternion q;
122 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
123#ifdef BOX
124 dBodySetPosition (boxbody, sx, sy+1, sz);
125 dBodySetLinearVel (boxbody, 0,0,0);
126 dBodySetAngularVel (boxbody, 0,0,0);
127 dBodySetQuaternion (boxbody, q);
128#endif
129#ifdef CYL
130 dBodySetPosition (cylbody, sx, sy, sz);
131 dBodySetLinearVel (cylbody, 0,0,0);
132 dBodySetAngularVel (cylbody, 0,0,0);
133 dBodySetQuaternion (cylbody, q);
134#endif
135}
136
137
138// called when a key pressed
139
140static void command (int cmd)
141{
142 switch (cmd)
143 {
144 case ' ':
145 reset_state();
146 break;
147 }
148}
149
150
151
152// simulation loop
153
154static void simLoop (int pause)
155{
156 double simstep = 0.005; // 5ms simulation steps
157 double dt = dsElapsedTime();
158 int nrofsteps = (int) ceilf(dt/simstep);
159 for (int i=0; i<nrofsteps && !pause; i++)
160 {
161 dSpaceCollide (space,0,&nearCallback);
162 dWorldQuickStep (world, simstep);
163 dJointGroupEmpty (contactgroup);
164 }
165
166 dsSetColor (1,1,1);
167#ifdef BOX
168 const dReal *BPos = dBodyGetPosition(boxbody);
169 const dReal *BRot = dBodyGetRotation(boxbody);
170 float bpos[3] = {BPos[0], BPos[1], BPos[2]};
171 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] };
172 float sides[3] = {BOXSZ, BOXSZ, BOXSZ};
173 dsDrawBox
174 (
175 bpos,
176 brot,
177 sides
178 ); // single precision
179#endif
180#ifdef CYL
181 const dReal *CPos = dGeomGetPosition(cylgeom);
182 const dReal *CRot = dGeomGetRotation(cylgeom);
183 float cpos[3] = {CPos[0], CPos[1], CPos[2]};
184 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] };
185 dsDrawCylinder
186 (
187// dBodyGetPosition(cylbody),
188// dBodyGetRotation(cylbody),
189 cpos,
190 crot,
191 WHEELW,
192 RADIUS
193 ); // single precision
194#endif
195
196 // draw world trimesh
197 dsSetColor(0.7,0.7,0.4);
198 dsSetTexture (DS_NONE);
199
200 const dReal* Pos = dGeomGetPosition(world_mesh);
201 float pos[3] = { Pos[0], Pos[1], Pos[2] };
202
203 const dReal* Rot = dGeomGetRotation(world_mesh);
204 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] };
205
206 int numi = sizeof(world_indices) / sizeof(int);
207
208 for (int i=0; i<numi/3; i++)
209 {
210 int i0 = world_indices[i*3+0];
211 int i1 = world_indices[i*3+1];
212 int i2 = world_indices[i*3+2];
213 float *v0 = world_vertices+i0*3;
214 float *v1 = world_vertices+i1*3;
215 float *v2 = world_vertices+i2*3;
216 dsDrawTriangle(pos, rot, v0,v1,v2, true); // single precision draw
217 }
218}
219
220
221int main (int argc, char **argv)
222{
223 dMass m;
224 dMatrix3 R;
225
226 // setup pointers to drawstuff callback functions
227 dsFunctions fn;
228 fn.version = DS_VERSION;
229 fn.start = &start;
230 fn.step = &simLoop;
231 fn.command = &command;
232 fn.stop = 0;
233 fn.path_to_textures = "../../drawstuff/textures";
234 if(argc==2)
235 {
236 fn.path_to_textures = argv[1];
237 }
238
239 // create world
240 dInitODE();
241 world = dWorldCreate();
242 space = dHashSpaceCreate (0);
243 contactgroup = dJointGroupCreate (0);
244 dWorldSetGravity (world,0,0,-9.8);
245 dWorldSetQuickStepNumIterations (world, 12);
246
247
248 // Create a static world using a triangle mesh that we can collide with.
249 int numv = sizeof(world_vertices)/(3*sizeof(float));
250 int numi = sizeof(world_indices)/ sizeof(int);
251 printf("numv=%d, numi=%d\n", numv, numi);
252 dTriMeshDataID Data = dGeomTriMeshDataCreate();
253
254 dGeomTriMeshDataBuildSingle
255 (
256 Data,
257 world_vertices,
258 3 * sizeof(float),
259 numv,
260 world_indices,
261 numi,
262 3 * sizeof(int)
263 );
264
265 world_mesh = dCreateTriMesh(space, Data, 0, 0, 0);
266 dGeomSetPosition(world_mesh, 0, 0, 0.5);
267 dRFromAxisAndAngle (R, 0,1,0, 0.0);
268 dGeomSetRotation (world_mesh, R);
269
270
271#ifdef BOX
272 boxbody = dBodyCreate (world);
273 dMassSetBox (&m,1, BOXSZ, BOXSZ, BOXSZ);
274 dMassAdjust (&m, 1);
275 dBodySetMass (boxbody,&m);
276 boxgeom = dCreateBox (0, BOXSZ, BOXSZ, BOXSZ);
277 dGeomSetBody (boxgeom,boxbody);
278 dSpaceAdd (space, boxgeom);
279#endif
280#ifdef CYL
281 cylbody = dBodyCreate (world);
282 dMassSetSphere (&m,1,RADIUS);
283 dMassAdjust (&m,WMASS);
284 dBodySetMass (cylbody,&m);
285 cylgeom = dCreateCylinder(0, RADIUS, WHEELW);
286 dGeomSetBody (cylgeom,cylbody);
287
288 #if defined(CYL_GEOM_OFFSET)
289 dMatrix3 mat;
290 dRFromAxisAndAngle(mat,1.0f,0.0f,0.0f,M_PI/2.0);
291 dGeomSetOffsetRotation(cylgeom,mat);
292 #endif
293
294 dSpaceAdd (space, cylgeom);
295#endif
296 reset_state();
297
298 // run simulation
299 dsSimulationLoop (argc,argv,352,288,&fn);
300
301 dJointGroupEmpty (contactgroup);
302 dJointGroupDestroy (contactgroup);
303
304 // First destroy geoms, then space, then the world.
305#ifdef CYL
306 dGeomDestroy (cylgeom);
307#endif
308#ifdef BOX
309 dGeomDestroy (boxgeom);
310#endif
311 dGeomDestroy (world_mesh);
312
313 dSpaceDestroy (space);
314 dWorldDestroy (world);
315 dCloseODE();
316 return 0;
317}
318
diff --git a/libraries/ode-0.9/ode/demo/demo_cylvssphere.cpp b/libraries/ode-0.9/ode/demo/demo_cylvssphere.cpp
deleted file mode 100644
index 1fb98ad..0000000
--- a/libraries/ode-0.9/ode/demo/demo_cylvssphere.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// Test for cylinder vs sphere, by Bram Stolk
24
25#include <ode/config.h>
26#include <assert.h>
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30#include <ode/ode.h>
31#include <drawstuff/drawstuff.h>
32
33#ifdef _MSC_VER
34#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
35#endif
36
37
38// dynamics and collision objects (chassis, 3 wheels, environment)
39
40static dWorldID world;
41static dSpaceID space;
42
43static dBodyID cylbody;
44static dGeomID cylgeom;
45
46static dBodyID sphbody;
47static dGeomID sphgeom;
48
49static dJointGroupID contactgroup;
50static dGeomID world_mesh;
51
52static bool show_contacts = true;
53
54#define CYLRADIUS 0.6
55#define CYLLENGTH 2.0
56#define SPHERERADIUS 0.5
57
58
59#ifdef dDOUBLE
60#define dsDrawBox dsDrawBoxD
61#define dsDrawLine dsDrawLineD
62#endif
63
64
65
66// this is called by dSpaceCollide when two objects in space are
67// potentially colliding.
68
69static void nearCallback (void *data, dGeomID o1, dGeomID o2)
70{
71 assert(o1);
72 assert(o2);
73
74 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
75 {
76 fprintf(stderr,"testing space %p %p\n", o1,o2);
77 // colliding a space with something
78 dSpaceCollide2(o1,o2,data,&nearCallback);
79 // Note we do not want to test intersections within a space,
80 // only between spaces.
81 return;
82 }
83
84 const int N = 32;
85 dContact contact[N];
86 int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
87 if (n > 0)
88 {
89 for (int i=0; i<n; i++)
90 {
91 contact[i].surface.mode = 0;
92 contact[i].surface.mu = 50.0; // was: dInfinity
93 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
94 dJointAttach (c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
95 if (show_contacts)
96 {
97 dMatrix3 RI;
98 dRSetIdentity (RI);
99 const dReal ss[3] = {0.12,0.12,0.12};
100 dsSetColorAlpha (0,0,1,0.5);
101 dsDrawBox (contact[i].geom.pos,RI,ss);
102 dReal *pos = contact[i].geom.pos;
103 dReal depth = contact[i].geom.depth;
104 dReal *norm = contact[i].geom.normal;
105 dReal endp[3] = {pos[0]+depth*norm[0], pos[1]+depth*norm[1], pos[2]+depth*norm[2]};
106 dsSetColorAlpha (1,1,1,1);
107 dsDrawLine (contact[i].geom.pos, endp);
108 }
109 }
110 }
111}
112
113
114// start simulation - set viewpoint
115
116static void start()
117{
118 static float xyz[3] = {-8,-9,3};
119 static float hpr[3] = {45.0000f,-27.5000f,0.0000f};
120 dsSetViewpoint (xyz,hpr);
121}
122
123
124// called when a key pressed
125
126static void command (int cmd)
127{
128 switch (cmd)
129 {
130 case ' ':
131 break;
132 }
133}
134
135
136
137// simulation loop
138
139static void simLoop (int pause)
140{
141 dSpaceCollide (space,0,&nearCallback);
142 if (!pause)
143 {
144 dWorldQuickStep (world, 0.01); // 100 Hz
145 }
146 dJointGroupEmpty (contactgroup);
147
148 dsSetColorAlpha (1,1,0,0.5);
149
150 const dReal *CPos = dBodyGetPosition(cylbody);
151 const dReal *CRot = dBodyGetRotation(cylbody);
152 float cpos[3] = {CPos[0], CPos[1], CPos[2]};
153 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] };
154 dsDrawCylinder
155 (
156 cpos,
157 crot,
158 CYLLENGTH,
159 CYLRADIUS
160 ); // single precision
161
162 const dReal *SPos = dBodyGetPosition(sphbody);
163 const dReal *SRot = dBodyGetRotation(sphbody);
164 float spos[3] = {SPos[0], SPos[1], SPos[2]};
165 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] };
166 dsDrawSphere
167 (
168 spos,
169 srot,
170 SPHERERADIUS
171 ); // single precision
172}
173
174
175int main (int argc, char **argv)
176{
177 dMass m;
178
179 // setup pointers to drawstuff callback functions
180 dsFunctions fn;
181 fn.version = DS_VERSION;
182 fn.start = &start;
183 fn.step = &simLoop;
184 fn.command = &command;
185 fn.stop = 0;
186 fn.path_to_textures = "../../drawstuff/textures";
187 if(argc==2)
188 fn.path_to_textures = argv[1];
189
190 // create world
191 dInitODE();
192 world = dWorldCreate();
193 space = dHashSpaceCreate (0);
194 contactgroup = dJointGroupCreate (0);
195 dWorldSetGravity (world,0,0,-9.8);
196 dWorldSetQuickStepNumIterations (world, 32);
197
198 dCreatePlane (space,0,0,1, 0.0);
199
200 cylbody = dBodyCreate (world);
201 dQuaternion q;
202#if 0
203 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
204#else
205// dQFromAxisAndAngle (q,1,0,0, M_PI * 1.0);
206 dQFromAxisAndAngle (q,1,0,0, M_PI * -0.77);
207#endif
208 dBodySetQuaternion (cylbody,q);
209 dMassSetCylinder (&m,1.0,3,CYLRADIUS,CYLLENGTH);
210 dBodySetMass (cylbody,&m);
211 cylgeom = dCreateCylinder(0, CYLRADIUS, CYLLENGTH);
212 dGeomSetBody (cylgeom,cylbody);
213 dBodySetPosition (cylbody, 0, 0, 3);
214 dSpaceAdd (space, cylgeom);
215
216 sphbody = dBodyCreate (world);
217 dMassSetSphere (&m,1,SPHERERADIUS);
218 dBodySetMass (sphbody,&m);
219 sphgeom = dCreateSphere(0, SPHERERADIUS);
220 dGeomSetBody (sphgeom,sphbody);
221 dBodySetPosition (sphbody, 0, 0, 5.5);
222 dSpaceAdd (space, sphgeom);
223
224 // run simulation
225 dsSimulationLoop (argc,argv,352,288,&fn);
226
227 dJointGroupEmpty (contactgroup);
228 dJointGroupDestroy (contactgroup);
229
230 dGeomDestroy(sphgeom);
231 dGeomDestroy (cylgeom);
232
233 dSpaceDestroy (space);
234 dWorldDestroy (world);
235 dCloseODE();
236 return 0;
237}
238
diff --git a/libraries/ode-0.9/ode/demo/demo_feedback.cpp b/libraries/ode-0.9/ode/demo/demo_feedback.cpp
deleted file mode 100644
index fd49278..0000000
--- a/libraries/ode-0.9/ode/demo/demo_feedback.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// Test for breaking joints, by Bram Stolk
24
25#include <ode/config.h>
26#include <assert.h>
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30#include <ode/ode.h>
31#include <drawstuff/drawstuff.h>
32
33
34#ifdef _MSC_VER
35#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
36#endif
37
38#ifdef dDOUBLE
39#define dsDrawBox dsDrawBoxD
40#define dsDrawCylinder dsDrawCylinderD
41#endif
42
43
44// dynamics and collision objects (chassis, 3 wheels, environment)
45
46static dWorldID world;
47static dSpaceID space;
48
49static const int STACKCNT=10; // nr of weights on bridge
50static const int SEGMCNT=16; // nr of segments in bridge
51static const float SEGMDIM[3] = { 0.9, 4, 0.1 };
52
53static dGeomID groundgeom;
54static dBodyID segbodies[SEGMCNT];
55static dGeomID seggeoms[SEGMCNT];
56static dBodyID stackbodies[STACKCNT];
57static dGeomID stackgeoms[STACKCNT];
58static dJointID hinges[SEGMCNT-1];
59static dJointID sliders[2];
60static dJointFeedback jfeedbacks[SEGMCNT-1];
61static dReal colours[SEGMCNT];
62static int stress[SEGMCNT-1];
63
64static dJointGroupID contactgroup;
65
66
67// this is called by dSpaceCollide when two objects in space are
68// potentially colliding.
69
70static void nearCallback (void *data, dGeomID o1, dGeomID o2)
71{
72 assert(o1);
73 assert(o2);
74
75 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
76 {
77 fprintf(stderr,"testing space %p %p\n", o1,o2);
78 // colliding a space with something
79 dSpaceCollide2(o1,o2,data,&nearCallback);
80 // Note we do not want to test intersections within a space,
81 // only between spaces.
82 return;
83 }
84
85 const int N = 32;
86 dContact contact[N];
87 int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
88 if (n > 0)
89 {
90 for (int i=0; i<n; i++)
91 {
92 contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1;
93 contact[i].surface.mu = 100.0;
94 contact[i].surface.soft_erp = 0.96;
95 contact[i].surface.soft_cfm = 0.02;
96 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
97 dJointAttach (c,
98 dGeomGetBody(contact[i].geom.g1),
99 dGeomGetBody(contact[i].geom.g2));
100 }
101 }
102}
103
104
105// start simulation - set viewpoint
106
107static void start()
108{
109 static float xyz[3] = { -6, 8, 6};
110 static float hpr[3] = { -65.0f, -27.0f, 0.0f};
111 dsSetViewpoint (xyz,hpr);
112}
113
114
115
116// called when a key pressed
117
118static void command (int cmd)
119{
120}
121
122
123
124void drawGeom (dGeomID g)
125{
126 const dReal *pos = dGeomGetPosition(g);
127 const dReal *R = dGeomGetRotation(g);
128
129 int type = dGeomGetClass (g);
130 if (type == dBoxClass)
131 {
132 dVector3 sides;
133 dGeomBoxGetLengths (g, sides);
134 dsDrawBox (pos,R,sides);
135 }
136 if (type == dCylinderClass)
137 {
138 dReal r,l;
139 dGeomCylinderGetParams(g, &r, &l);
140 dsDrawCylinder (pos, R, l, r);
141 }
142}
143
144
145static void inspectJoints(void)
146{
147 const dReal forcelimit = 2000.0;
148 int i;
149 for (i=0; i<SEGMCNT-1; i++)
150 {
151 if (dJointGetBody(hinges[i], 0))
152 {
153 // This joint has not snapped already... inspect it.
154 dReal l0 = dLENGTH(jfeedbacks[i].f1);
155 dReal l1 = dLENGTH(jfeedbacks[i].f2);
156 colours[i+0] = 0.95*colours[i+0] + 0.05 * l0/forcelimit;
157 colours[i+1] = 0.95*colours[i+1] + 0.05 * l1/forcelimit;
158 if (l0 > forcelimit || l1 > forcelimit)
159 stress[i]++;
160 else
161 stress[i]=0;
162 if (stress[i]>4)
163 {
164 // Low-pass filter the noisy feedback data.
165 // Only after 4 consecutive timesteps with excessive load, snap.
166 fprintf(stderr,"SNAP! (that was the sound of joint %d breaking)\n", i);
167 dJointAttach (hinges[i], 0, 0);
168 }
169 }
170 }
171}
172
173
174// simulation loop
175
176static void simLoop (int pause)
177{
178 int i;
179
180 double simstep = 0.005; // 5ms simulation steps
181 double dt = dsElapsedTime();
182 int nrofsteps = (int) ceilf(dt/simstep);
183 for (i=0; i<nrofsteps && !pause; i++)
184 {
185 dSpaceCollide (space,0,&nearCallback);
186 dWorldQuickStep (world, simstep);
187 dJointGroupEmpty (contactgroup);
188 inspectJoints();
189 }
190
191 for (i=0; i<SEGMCNT; i++)
192 {
193 float r=0,g=0,b=0.2;
194 float v = colours[i];
195 if (v>1.0) v=1.0;
196 if (v<0.5)
197 {
198 r=2*v;
199 g=1.0;
200 }
201 else
202 {
203 r=1.0;
204 g=2*(1.0-v);
205 }
206 dsSetColor (r,g,b);
207 drawGeom(seggeoms[i]);
208 }
209 dsSetColor (1,1,1);
210 for (i=0; i<STACKCNT; i++)
211 drawGeom(stackgeoms[i]);
212}
213
214
215
216int main (int argc, char **argv)
217{
218 dMass m;
219
220 // setup pointers to drawstuff callback functions
221 dsFunctions fn;
222 fn.version = DS_VERSION;
223 fn.start = &start;
224 fn.step = &simLoop;
225 fn.command = &command;
226 fn.stop = 0;
227 fn.path_to_textures = "../../drawstuff/textures";
228 if(argc==2)
229 {
230 fn.path_to_textures = argv[1];
231 }
232
233 // create world
234 dInitODE();
235 world = dWorldCreate();
236 space = dHashSpaceCreate (0);
237 contactgroup = dJointGroupCreate (0);
238 dWorldSetGravity (world,0,0,-9.8);
239 dWorldSetQuickStepNumIterations (world, 20);
240
241 int i;
242 for (i=0; i<SEGMCNT; i++)
243 {
244 segbodies[i] = dBodyCreate (world);
245 dBodySetPosition(segbodies[i], i - SEGMCNT/2.0, 0, 5);
246 dMassSetBox (&m, 1, SEGMDIM[0], SEGMDIM[1], SEGMDIM[2]);
247 dBodySetMass (segbodies[i], &m);
248 seggeoms[i] = dCreateBox (0, SEGMDIM[0], SEGMDIM[1], SEGMDIM[2]);
249 dGeomSetBody (seggeoms[i], segbodies[i]);
250 dSpaceAdd (space, seggeoms[i]);
251 }
252
253 for (i=0; i<SEGMCNT-1; i++)
254 {
255 hinges[i] = dJointCreateHinge (world,0);
256 dJointAttach (hinges[i], segbodies[i],segbodies[i+1]);
257 dJointSetHingeAnchor (hinges[i], i + 0.5 - SEGMCNT/2.0, 0, 5);
258 dJointSetHingeAxis (hinges[i], 0,1,0);
259 dJointSetHingeParam (hinges[i],dParamFMax, 8000.0);
260 // NOTE:
261 // Here we tell ODE where to put the feedback on the forces for this hinge
262 dJointSetFeedback (hinges[i], jfeedbacks+i);
263 stress[i]=0;
264 }
265
266 for (i=0; i<STACKCNT; i++)
267 {
268 stackbodies[i] = dBodyCreate(world);
269 dMassSetBox (&m, 2.0, 2, 2, 0.6);
270 dBodySetMass(stackbodies[i],&m);
271
272 stackgeoms[i] = dCreateBox(0, 2, 2, 0.6);
273 dGeomSetBody(stackgeoms[i], stackbodies[i]);
274 dBodySetPosition(stackbodies[i], 0,0,8+2*i);
275 dSpaceAdd(space, stackgeoms[i]);
276 }
277
278 sliders[0] = dJointCreateSlider (world,0);
279 dJointAttach(sliders[0], segbodies[0], 0);
280 dJointSetSliderAxis (sliders[0], 1,0,0);
281 dJointSetSliderParam (sliders[0],dParamFMax, 4000.0);
282 dJointSetSliderParam (sliders[0],dParamLoStop, 0.0);
283 dJointSetSliderParam (sliders[0],dParamHiStop, 0.2);
284
285 sliders[1] = dJointCreateSlider (world,0);
286 dJointAttach(sliders[1], segbodies[SEGMCNT-1], 0);
287 dJointSetSliderAxis (sliders[1], 1,0,0);
288 dJointSetSliderParam (sliders[1],dParamFMax, 4000.0);
289 dJointSetSliderParam (sliders[1],dParamLoStop, 0.0);
290 dJointSetSliderParam (sliders[1],dParamHiStop, -0.2);
291
292 groundgeom = dCreatePlane(space, 0,0,1,0);
293
294 for (i=0; i<SEGMCNT; i++)
295 colours[i]=0.0;
296
297 // run simulation
298 dsSimulationLoop (argc,argv,352,288,&fn);
299
300 dJointGroupEmpty (contactgroup);
301 dJointGroupDestroy (contactgroup);
302
303 // First destroy seggeoms, then space, then the world.
304 for (i=0; i<SEGMCNT; i++)
305 dGeomDestroy (seggeoms[i]);
306 for (i=0; i<STACKCNT; i++)
307 dGeomDestroy (stackgeoms[i]);
308
309 dSpaceDestroy(space);
310 dWorldDestroy (world);
311 dCloseODE();
312 return 0;
313}
314
diff --git a/libraries/ode-0.9/ode/demo/demo_friction.cpp b/libraries/ode-0.9/ode/demo/demo_friction.cpp
deleted file mode 100644
index 36ba2d4..0000000
--- a/libraries/ode-0.9/ode/demo/demo_friction.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25test the Coulomb friction approximation.
26
27a 10x10 array of boxes is made, each of which rests on the ground.
28a horizantal force is applied to each box to try and get it to slide.
29box[i][j] has a mass (i+1)*MASS and a force (j+1)*FORCE. by the Coloumb
30friction model, the box should only slide if the force is greater than MU
31times the contact normal force, i.e.
32
33 f > MU * body_mass * GRAVITY
34 (j+1)*FORCE > MU * (i+1)*MASS * GRAVITY
35 (j+1) > (i+1) * (MU*MASS*GRAVITY/FORCE)
36 (j+1) > (i+1) * k
37
38this should be independent of the number of contact points, as N contact
39points will each have 1/N'th the normal force but the pushing force will
40have to overcome N contacts. the constants are chosen so that k=1.
41thus you should see a triangle made of half the bodies in the array start to
42slide.
43
44*/
45
46
47#include <ode/ode.h>
48#include <drawstuff/drawstuff.h>
49
50#ifdef _MSC_VER
51#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
52#endif
53
54// select correct drawing functions
55
56#ifdef dDOUBLE
57#define dsDrawBox dsDrawBoxD
58#define dsDrawSphere dsDrawSphereD
59#define dsDrawCylinder dsDrawCylinderD
60#define dsDrawCapsule dsDrawCapsuleD
61#endif
62
63
64// some constants
65
66#define LENGTH 0.2 // box length & width
67#define HEIGHT 0.05 // box height
68#define MASS 0.2 // mass of box[i][j] = (i+1) * MASS
69#define FORCE 0.05 // force applied to box[i][j] = (j+1) * FORCE
70#define MU 0.5 // the global mu to use
71#define GRAVITY 0.5 // the global gravity to use
72#define N1 10 // number of different forces to try
73#define N2 10 // number of different masses to try
74
75
76// dynamics and collision objects
77
78static dWorldID world;
79static dSpaceID space;
80static dBodyID body[N1][N2];
81static dJointGroupID contactgroup;
82static dGeomID ground;
83static dGeomID box[N1][N2];
84
85
86
87// this is called by dSpaceCollide when two objects in space are
88// potentially colliding.
89
90static void nearCallback (void *data, dGeomID o1, dGeomID o2)
91{
92 int i;
93
94 // only collide things with the ground
95 int g1 = (o1 == ground);
96 int g2 = (o2 == ground);
97 if (!(g1 ^ g2)) return;
98
99 dBodyID b1 = dGeomGetBody(o1);
100 dBodyID b2 = dGeomGetBody(o2);
101
102 dContact contact[3]; // up to 3 contacts per box
103 for (i=0; i<3; i++) {
104 contact[i].surface.mode = dContactSoftCFM | dContactApprox1;
105 contact[i].surface.mu = MU;
106 contact[i].surface.soft_cfm = 0.01;
107 }
108 if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
109 for (i=0; i<numc; i++) {
110 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
111 dJointAttach (c,b1,b2);
112 }
113 }
114}
115
116
117// start simulation - set viewpoint
118
119static void start()
120{
121 static float xyz[3] = {1.7772,-0.7924,2.7600};
122 static float hpr[3] = {90.0000,-54.0000,0.0000};
123 dsSetViewpoint (xyz,hpr);
124}
125
126
127// simulation loop
128
129static void simLoop (int pause)
130{
131 int i;
132 if (!pause) {
133 // apply forces to all bodies
134 for (i=0; i<N1; i++) {
135 for (int j=0; j<N2; j++) {
136 dBodyAddForce (body[i][j],FORCE*(i+1),0,0);
137 }
138 }
139
140 dSpaceCollide (space,0,&nearCallback);
141 dWorldStep (world,0.05);
142
143 // remove all contact joints
144 dJointGroupEmpty (contactgroup);
145 }
146
147 dsSetColor (1,0,1);
148 dReal sides[3] = {LENGTH,LENGTH,HEIGHT};
149 for (i=0; i<N1; i++) {
150 for (int j=0; j<N2; j++) {
151 dsDrawBox (dGeomGetPosition(box[i][j]),dGeomGetRotation(box[i][j]),
152 sides);
153 }
154 }
155}
156
157
158int main (int argc, char **argv)
159{
160 int i,j;
161 dMass m;
162
163 // setup pointers to drawstuff callback functions
164 dsFunctions fn;
165 fn.version = DS_VERSION;
166 fn.start = &start;
167 fn.step = &simLoop;
168 fn.command = 0;
169 fn.stop = 0;
170 fn.path_to_textures = "../../drawstuff/textures";
171 if(argc==2)
172 {
173 fn.path_to_textures = argv[1];
174 }
175
176 // create world
177 dInitODE();
178 world = dWorldCreate();
179 space = dHashSpaceCreate (0);
180 contactgroup = dJointGroupCreate (0);
181 dWorldSetGravity (world,0,0,-GRAVITY);
182 ground = dCreatePlane (space,0,0,1,0);
183
184 // bodies
185 for (i=0; i<N1; i++) {
186 for (j=0; j<N2; j++) {
187 body[i][j] = dBodyCreate (world);
188 dMassSetBox (&m,1,LENGTH,LENGTH,HEIGHT);
189 dMassAdjust (&m,MASS*(j+1));
190 dBodySetMass (body[i][j],&m);
191 dBodySetPosition (body[i][j],i*2*LENGTH,j*2*LENGTH,HEIGHT*0.5);
192
193 box[i][j] = dCreateBox (space,LENGTH,LENGTH,HEIGHT);
194 dGeomSetBody (box[i][j],body[i][j]);
195 }
196 }
197
198 // run simulation
199 dsSimulationLoop (argc,argv,352,288,&fn);
200
201 dJointGroupDestroy (contactgroup);
202 dSpaceDestroy (space);
203 dWorldDestroy (world);
204 dCloseODE();
205 return 0;
206}
diff --git a/libraries/ode-0.9/ode/demo/demo_heightfield.cpp b/libraries/ode-0.9/ode/demo/demo_heightfield.cpp
deleted file mode 100644
index 83156ab..0000000
--- a/libraries/ode-0.9/ode/demo/demo_heightfield.cpp
+++ /dev/null
@@ -1,2132 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30#define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
31
32
33// Our heightfield geom
34dGeomID gheight;
35
36
37
38// Heightfield dimensions
39
40#define HFIELD_WSTEP 15 // Vertex count along edge >= 2
41#define HFIELD_DSTEP 31
42
43#define HFIELD_WIDTH REAL( 4.0 )
44#define HFIELD_DEPTH REAL( 8.0 )
45
46#define HFIELD_WSAMP ( HFIELD_WIDTH / ( HFIELD_WSTEP-1 ) )
47#define HFIELD_DSAMP ( HFIELD_DEPTH / ( HFIELD_DSTEP-1 ) )
48
49#ifdef dDOUBLE
50#define dsDrawBox dsDrawBoxD
51#define dsDrawSphere dsDrawSphereD
52#define dsDrawCylinder dsDrawCylinderD
53#define dsDrawCapsule dsDrawCapsuleD
54#define dsDrawConvex dsDrawConvexD
55#define dsDrawTriangle dsDrawTriangleD
56#endif
57
58
59
60//<---- Convex Object
61dReal planes[]= // planes for a cube
62 {
63 1.0f ,0.0f ,0.0f ,0.25f,
64 0.0f ,1.0f ,0.0f ,0.25f,
65 0.0f ,0.0f ,1.0f ,0.25f,
66 0.0f ,0.0f ,-1.0f,0.25f,
67 0.0f ,-1.0f,0.0f ,0.25f,
68 -1.0f,0.0f ,0.0f ,0.25f
69 /*
70 1.0f ,0.0f ,0.0f ,2.0f,
71 0.0f ,1.0f ,0.0f ,1.0f,
72 0.0f ,0.0f ,1.0f ,1.0f,
73 0.0f ,0.0f ,-1.0f,1.0f,
74 0.0f ,-1.0f,0.0f ,1.0f,
75 -1.0f,0.0f ,0.0f ,0.0f
76 */
77 };
78const unsigned int planecount=6;
79
80dReal points[]= // points for a cube
81 {
82 0.25f,0.25f,0.25f, // point 0
83 -0.25f,0.25f,0.25f, // point 1
84
85 0.25f,-0.25f,0.25f, // point 2
86 -0.25f,-0.25f,0.25f,// point 3
87
88 0.25f,0.25f,-0.25f, // point 4
89 -0.25f,0.25f,-0.25f,// point 5
90
91 0.25f,-0.25f,-0.25f,// point 6
92 -0.25f,-0.25f,-0.25f,// point 7
93 };
94const unsigned int pointcount=8;
95unsigned int polygons[] = //Polygons for a cube (6 squares)
96 {
97 4,0,2,6,4, // positive X
98 4,1,0,4,5, // positive Y
99 4,0,1,3,2, // positive Z
100 4,3,1,5,7, // negative X
101 4,2,3,7,6, // negative Y
102 4,5,4,6,7, // negative Z
103 };
104//----> Convex Object
105
106// select correct drawing functions
107
108#ifdef dDOUBLE
109#define dsDrawBox dsDrawBoxD
110#define dsDrawSphere dsDrawSphereD
111#define dsDrawCylinder dsDrawCylinderD
112#define dsDrawCapsule dsDrawCapsuleD
113#define dsDrawConvex dsDrawConvexD
114#endif
115
116
117// some constants
118
119#define NUM 100 // max number of objects
120#define DENSITY (5.0) // density of all objects
121#define GPB 3 // maximum number of geometries per body
122#define MAX_CONTACTS 64 // maximum number of contact points per body
123
124
125// dynamics and collision objects
126
127struct MyObject {
128 dBodyID body; // the body
129 dGeomID geom[GPB]; // geometries representing this body
130
131 // Trimesh only - double buffered matrices for 'last transform' setup
132 dReal matrix_dblbuff[ 16 * 2 ];
133 int last_matrix_index;
134};
135
136static int num=0; // number of objects in simulation
137static int nextobj=0; // next object to recycle if num==NUM
138static dWorldID world;
139static dSpaceID space;
140static MyObject obj[NUM];
141static dJointGroupID contactgroup;
142static int selected = -1; // selected object
143static int show_aabb = 0; // show geom AABBs?
144static int show_contacts = 0; // show contact points?
145static int random_pos = 1; // drop objects from random position?
146static int write_world = 0;
147
148
149
150
151//============================
152
153// Bunny mesh ripped from Opcode
154const int VertexCount = 453;
155const int IndexCount = 902 * 3;
156
157typedef dReal dVector3R[3];
158
159dGeomID TriMesh1;
160dGeomID TriMesh2;
161static dTriMeshDataID TriData1, TriData2; // reusable static trimesh data
162
163static float Vertices[VertexCount * 3] = {
164 REAL(-0.334392), REAL(0.133007), REAL(0.062259),
165 REAL(-0.350189), REAL(0.150354), REAL(-0.147769),
166 REAL(-0.234201), REAL(0.343811), REAL(-0.174307),
167 REAL(-0.200259), REAL(0.285207), REAL(0.093749),
168 REAL(0.003520), REAL(0.475208), REAL(-0.159365),
169 REAL(0.001856), REAL(0.419203), REAL(0.098582),
170 REAL(-0.252802), REAL(0.093666), REAL(0.237538),
171 REAL(-0.162901), REAL(0.237984), REAL(0.206905),
172 REAL(0.000865), REAL(0.318141), REAL(0.235370),
173 REAL(-0.414624), REAL(0.164083), REAL(-0.278254),
174 REAL(-0.262213), REAL(0.357334), REAL(-0.293246),
175 REAL(0.004628), REAL(0.482694), REAL(-0.338626),
176 REAL(-0.402162), REAL(0.133528), REAL(-0.443247),
177 REAL(-0.243781), REAL(0.324275), REAL(-0.436763),
178 REAL(0.005293), REAL(0.437592), REAL(-0.458332),
179 REAL(-0.339884), REAL(-0.041150), REAL(-0.668211),
180 REAL(-0.248382), REAL(0.255825), REAL(-0.627493),
181 REAL(0.006261), REAL(0.376103), REAL(-0.631506),
182 REAL(-0.216201), REAL(-0.126776), REAL(-0.886936),
183 REAL(-0.171075), REAL(0.011544), REAL(-0.881386),
184 REAL(-0.181074), REAL(0.098223), REAL(-0.814779),
185 REAL(-0.119891), REAL(0.218786), REAL(-0.760153),
186 REAL(-0.078895), REAL(0.276780), REAL(-0.739281),
187 REAL(0.006801), REAL(0.310959), REAL(-0.735661),
188 REAL(-0.168842), REAL(0.102387), REAL(-0.920381),
189 REAL(-0.104072), REAL(0.177278), REAL(-0.952530),
190 REAL(-0.129704), REAL(0.211848), REAL(-0.836678),
191 REAL(-0.099875), REAL(0.310931), REAL(-0.799381),
192 REAL(0.007237), REAL(0.361687), REAL(-0.794439),
193 REAL(-0.077913), REAL(0.258753), REAL(-0.921640),
194 REAL(0.007957), REAL(0.282241), REAL(-0.931680),
195 REAL(-0.252222), REAL(-0.550401), REAL(-0.557810),
196 REAL(-0.267633), REAL(-0.603419), REAL(-0.655209),
197 REAL(-0.446838), REAL(-0.118517), REAL(-0.466159),
198 REAL(-0.459488), REAL(-0.093017), REAL(-0.311341),
199 REAL(-0.370645), REAL(-0.100108), REAL(-0.159454),
200 REAL(-0.371984), REAL(-0.091991), REAL(-0.011044),
201 REAL(-0.328945), REAL(-0.098269), REAL(0.088659),
202 REAL(-0.282452), REAL(-0.018862), REAL(0.311501),
203 REAL(-0.352403), REAL(-0.131341), REAL(0.144902),
204 REAL(-0.364126), REAL(-0.200299), REAL(0.202388),
205 REAL(-0.283965), REAL(-0.231869), REAL(0.023668),
206 REAL(-0.298943), REAL(-0.155218), REAL(0.369716),
207 REAL(-0.293787), REAL(-0.121856), REAL(0.419097),
208 REAL(-0.290163), REAL(-0.290797), REAL(0.107824),
209 REAL(-0.264165), REAL(-0.272849), REAL(0.036347),
210 REAL(-0.228567), REAL(-0.372573), REAL(0.290309),
211 REAL(-0.190431), REAL(-0.286997), REAL(0.421917),
212 REAL(-0.191039), REAL(-0.240973), REAL(0.507118),
213 REAL(-0.287272), REAL(-0.276431), REAL(-0.065444),
214 REAL(-0.295675), REAL(-0.280818), REAL(-0.174200),
215 REAL(-0.399537), REAL(-0.313131), REAL(-0.376167),
216 REAL(-0.392666), REAL(-0.488581), REAL(-0.427494),
217 REAL(-0.331669), REAL(-0.570185), REAL(-0.466054),
218 REAL(-0.282290), REAL(-0.618140), REAL(-0.589220),
219 REAL(-0.374238), REAL(-0.594882), REAL(-0.323298),
220 REAL(-0.381071), REAL(-0.629723), REAL(-0.350777),
221 REAL(-0.382112), REAL(-0.624060), REAL(-0.221577),
222 REAL(-0.272701), REAL(-0.566522), REAL(0.259157),
223 REAL(-0.256702), REAL(-0.663406), REAL(0.286079),
224 REAL(-0.280948), REAL(-0.428359), REAL(0.055790),
225 REAL(-0.184974), REAL(-0.508894), REAL(0.326265),
226 REAL(-0.279971), REAL(-0.526918), REAL(0.395319),
227 REAL(-0.282599), REAL(-0.663393), REAL(0.412411),
228 REAL(-0.188329), REAL(-0.475093), REAL(0.417954),
229 REAL(-0.263384), REAL(-0.663396), REAL(0.466604),
230 REAL(-0.209063), REAL(-0.663393), REAL(0.509344),
231 REAL(-0.002044), REAL(-0.319624), REAL(0.553078),
232 REAL(-0.001266), REAL(-0.371260), REAL(0.413296),
233 REAL(-0.219753), REAL(-0.339762), REAL(-0.040921),
234 REAL(-0.256986), REAL(-0.282511), REAL(-0.006349),
235 REAL(-0.271706), REAL(-0.260881), REAL(0.001764),
236 REAL(-0.091191), REAL(-0.419184), REAL(-0.045912),
237 REAL(-0.114944), REAL(-0.429752), REAL(-0.124739),
238 REAL(-0.113970), REAL(-0.382987), REAL(-0.188540),
239 REAL(-0.243012), REAL(-0.464942), REAL(-0.242850),
240 REAL(-0.314815), REAL(-0.505402), REAL(-0.324768),
241 REAL(0.002774), REAL(-0.437526), REAL(-0.262766),
242 REAL(-0.072625), REAL(-0.417748), REAL(-0.221440),
243 REAL(-0.160112), REAL(-0.476932), REAL(-0.293450),
244 REAL(0.003859), REAL(-0.453425), REAL(-0.443916),
245 REAL(-0.120363), REAL(-0.581567), REAL(-0.438689),
246 REAL(-0.091499), REAL(-0.584191), REAL(-0.294511),
247 REAL(-0.116469), REAL(-0.599861), REAL(-0.188308),
248 REAL(-0.208032), REAL(-0.513640), REAL(-0.134649),
249 REAL(-0.235749), REAL(-0.610017), REAL(-0.040939),
250 REAL(-0.344916), REAL(-0.622487), REAL(-0.085380),
251 REAL(-0.336401), REAL(-0.531864), REAL(-0.212298),
252 REAL(0.001961), REAL(-0.459550), REAL(-0.135547),
253 REAL(-0.058296), REAL(-0.430536), REAL(-0.043440),
254 REAL(0.001378), REAL(-0.449511), REAL(-0.037762),
255 REAL(-0.130135), REAL(-0.510222), REAL(0.079144),
256 REAL(0.000142), REAL(-0.477549), REAL(0.157064),
257 REAL(-0.114284), REAL(-0.453206), REAL(0.304397),
258 REAL(-0.000592), REAL(-0.443558), REAL(0.285401),
259 REAL(-0.056215), REAL(-0.663402), REAL(0.326073),
260 REAL(-0.026248), REAL(-0.568010), REAL(0.273318),
261 REAL(-0.049261), REAL(-0.531064), REAL(0.389854),
262 REAL(-0.127096), REAL(-0.663398), REAL(0.479316),
263 REAL(-0.058384), REAL(-0.663401), REAL(0.372891),
264 REAL(-0.303961), REAL(0.054199), REAL(0.625921),
265 REAL(-0.268594), REAL(0.193403), REAL(0.502766),
266 REAL(-0.277159), REAL(0.126123), REAL(0.443289),
267 REAL(-0.287605), REAL(-0.005722), REAL(0.531844),
268 REAL(-0.231396), REAL(-0.121289), REAL(0.587387),
269 REAL(-0.253475), REAL(-0.081797), REAL(0.756541),
270 REAL(-0.195164), REAL(-0.137969), REAL(0.728011),
271 REAL(-0.167673), REAL(-0.156573), REAL(0.609388),
272 REAL(-0.145917), REAL(-0.169029), REAL(0.697600),
273 REAL(-0.077776), REAL(-0.214247), REAL(0.622586),
274 REAL(-0.076873), REAL(-0.214971), REAL(0.696301),
275 REAL(-0.002341), REAL(-0.233135), REAL(0.622859),
276 REAL(-0.002730), REAL(-0.213526), REAL(0.691267),
277 REAL(-0.003136), REAL(-0.192628), REAL(0.762731),
278 REAL(-0.056136), REAL(-0.201222), REAL(0.763806),
279 REAL(-0.114589), REAL(-0.166192), REAL(0.770723),
280 REAL(-0.155145), REAL(-0.129632), REAL(0.791738),
281 REAL(-0.183611), REAL(-0.058705), REAL(0.847012),
282 REAL(-0.165562), REAL(0.001980), REAL(0.833386),
283 REAL(-0.220084), REAL(0.019914), REAL(0.768935),
284 REAL(-0.255730), REAL(0.090306), REAL(0.670782),
285 REAL(-0.255594), REAL(0.113833), REAL(0.663389),
286 REAL(-0.226380), REAL(0.212655), REAL(0.617740),
287 REAL(-0.003367), REAL(-0.195342), REAL(0.799680),
288 REAL(-0.029743), REAL(-0.210508), REAL(0.827180),
289 REAL(-0.003818), REAL(-0.194783), REAL(0.873636),
290 REAL(-0.004116), REAL(-0.157907), REAL(0.931268),
291 REAL(-0.031280), REAL(-0.184555), REAL(0.889476),
292 REAL(-0.059885), REAL(-0.184448), REAL(0.841330),
293 REAL(-0.135333), REAL(-0.164332), REAL(0.878200),
294 REAL(-0.085574), REAL(-0.170948), REAL(0.925547),
295 REAL(-0.163833), REAL(-0.094170), REAL(0.897114),
296 REAL(-0.138444), REAL(-0.104250), REAL(0.945975),
297 REAL(-0.083497), REAL(-0.084934), REAL(0.979607),
298 REAL(-0.004433), REAL(-0.146642), REAL(0.985872),
299 REAL(-0.150715), REAL(0.032650), REAL(0.884111),
300 REAL(-0.135892), REAL(-0.035520), REAL(0.945455),
301 REAL(-0.070612), REAL(0.036849), REAL(0.975733),
302 REAL(-0.004458), REAL(-0.042526), REAL(1.015670),
303 REAL(-0.004249), REAL(0.046042), REAL(1.003240),
304 REAL(-0.086969), REAL(0.133224), REAL(0.947633),
305 REAL(-0.003873), REAL(0.161605), REAL(0.970499),
306 REAL(-0.125544), REAL(0.140012), REAL(0.917678),
307 REAL(-0.125651), REAL(0.250246), REAL(0.857602),
308 REAL(-0.003127), REAL(0.284070), REAL(0.878870),
309 REAL(-0.159174), REAL(0.125726), REAL(0.888878),
310 REAL(-0.183807), REAL(0.196970), REAL(0.844480),
311 REAL(-0.159890), REAL(0.291736), REAL(0.732480),
312 REAL(-0.199495), REAL(0.207230), REAL(0.779864),
313 REAL(-0.206182), REAL(0.164608), REAL(0.693257),
314 REAL(-0.186315), REAL(0.160689), REAL(0.817193),
315 REAL(-0.192827), REAL(0.166706), REAL(0.782271),
316 REAL(-0.175112), REAL(0.110008), REAL(0.860621),
317 REAL(-0.161022), REAL(0.057420), REAL(0.855111),
318 REAL(-0.172319), REAL(0.036155), REAL(0.816189),
319 REAL(-0.190318), REAL(0.064083), REAL(0.760605),
320 REAL(-0.195072), REAL(0.129179), REAL(0.731104),
321 REAL(-0.203126), REAL(0.410287), REAL(0.680536),
322 REAL(-0.216677), REAL(0.309274), REAL(0.642272),
323 REAL(-0.241515), REAL(0.311485), REAL(0.587832),
324 REAL(-0.002209), REAL(0.366663), REAL(0.749413),
325 REAL(-0.088230), REAL(0.396265), REAL(0.678635),
326 REAL(-0.170147), REAL(0.109517), REAL(0.840784),
327 REAL(-0.160521), REAL(0.067766), REAL(0.830650),
328 REAL(-0.181546), REAL(0.139805), REAL(0.812146),
329 REAL(-0.180495), REAL(0.148568), REAL(0.776087),
330 REAL(-0.180255), REAL(0.129125), REAL(0.744192),
331 REAL(-0.186298), REAL(0.078308), REAL(0.769352),
332 REAL(-0.167622), REAL(0.060539), REAL(0.806675),
333 REAL(-0.189876), REAL(0.102760), REAL(0.802582),
334 REAL(-0.108340), REAL(0.455446), REAL(0.657174),
335 REAL(-0.241585), REAL(0.527592), REAL(0.669296),
336 REAL(-0.265676), REAL(0.513366), REAL(0.634594),
337 REAL(-0.203073), REAL(0.478550), REAL(0.581526),
338 REAL(-0.266772), REAL(0.642330), REAL(0.602061),
339 REAL(-0.216961), REAL(0.564846), REAL(0.535435),
340 REAL(-0.202210), REAL(0.525495), REAL(0.475944),
341 REAL(-0.193888), REAL(0.467925), REAL(0.520606),
342 REAL(-0.265837), REAL(0.757267), REAL(0.500933),
343 REAL(-0.240306), REAL(0.653440), REAL(0.463215),
344 REAL(-0.309239), REAL(0.776868), REAL(0.304726),
345 REAL(-0.271009), REAL(0.683094), REAL(0.382018),
346 REAL(-0.312111), REAL(0.671099), REAL(0.286687),
347 REAL(-0.268791), REAL(0.624342), REAL(0.377231),
348 REAL(-0.302457), REAL(0.533996), REAL(0.360289),
349 REAL(-0.263656), REAL(0.529310), REAL(0.412564),
350 REAL(-0.282311), REAL(0.415167), REAL(0.447666),
351 REAL(-0.239201), REAL(0.442096), REAL(0.495604),
352 REAL(-0.220043), REAL(0.569026), REAL(0.445877),
353 REAL(-0.001263), REAL(0.395631), REAL(0.602029),
354 REAL(-0.057345), REAL(0.442535), REAL(0.572224),
355 REAL(-0.088927), REAL(0.506333), REAL(0.529106),
356 REAL(-0.125738), REAL(0.535076), REAL(0.612913),
357 REAL(-0.126251), REAL(0.577170), REAL(0.483159),
358 REAL(-0.149594), REAL(0.611520), REAL(0.557731),
359 REAL(-0.163188), REAL(0.660791), REAL(0.491080),
360 REAL(-0.172482), REAL(0.663387), REAL(0.415416),
361 REAL(-0.160464), REAL(0.591710), REAL(0.370659),
362 REAL(-0.156445), REAL(0.536396), REAL(0.378302),
363 REAL(-0.136496), REAL(0.444358), REAL(0.425226),
364 REAL(-0.095564), REAL(0.373768), REAL(0.473659),
365 REAL(-0.104146), REAL(0.315912), REAL(0.498104),
366 REAL(-0.000496), REAL(0.384194), REAL(0.473817),
367 REAL(-0.000183), REAL(0.297770), REAL(0.401486),
368 REAL(-0.129042), REAL(0.270145), REAL(0.434495),
369 REAL(0.000100), REAL(0.272963), REAL(0.349138),
370 REAL(-0.113060), REAL(0.236984), REAL(0.385554),
371 REAL(0.007260), REAL(0.016311), REAL(-0.883396),
372 REAL(0.007865), REAL(0.122104), REAL(-0.956137),
373 REAL(-0.032842), REAL(0.115282), REAL(-0.953252),
374 REAL(-0.089115), REAL(0.108449), REAL(-0.950317),
375 REAL(-0.047440), REAL(0.014729), REAL(-0.882756),
376 REAL(-0.104458), REAL(0.013137), REAL(-0.882070),
377 REAL(-0.086439), REAL(-0.584866), REAL(-0.608343),
378 REAL(-0.115026), REAL(-0.662605), REAL(-0.436732),
379 REAL(-0.071683), REAL(-0.665372), REAL(-0.606385),
380 REAL(-0.257884), REAL(-0.665381), REAL(-0.658052),
381 REAL(-0.272542), REAL(-0.665381), REAL(-0.592063),
382 REAL(-0.371322), REAL(-0.665382), REAL(-0.353620),
383 REAL(-0.372362), REAL(-0.665381), REAL(-0.224420),
384 REAL(-0.335166), REAL(-0.665380), REAL(-0.078623),
385 REAL(-0.225999), REAL(-0.665375), REAL(-0.038981),
386 REAL(-0.106719), REAL(-0.665374), REAL(-0.186351),
387 REAL(-0.081749), REAL(-0.665372), REAL(-0.292554),
388 REAL(0.006943), REAL(-0.091505), REAL(-0.858354),
389 REAL(0.006117), REAL(-0.280985), REAL(-0.769967),
390 REAL(0.004495), REAL(-0.502360), REAL(-0.559799),
391 REAL(-0.198638), REAL(-0.302135), REAL(-0.845816),
392 REAL(-0.237395), REAL(-0.542544), REAL(-0.587188),
393 REAL(-0.270001), REAL(-0.279489), REAL(-0.669861),
394 REAL(-0.134547), REAL(-0.119852), REAL(-0.959004),
395 REAL(-0.052088), REAL(-0.122463), REAL(-0.944549),
396 REAL(-0.124463), REAL(-0.293508), REAL(-0.899566),
397 REAL(-0.047616), REAL(-0.289643), REAL(-0.879292),
398 REAL(-0.168595), REAL(-0.529132), REAL(-0.654931),
399 REAL(-0.099793), REAL(-0.515719), REAL(-0.645873),
400 REAL(-0.186168), REAL(-0.605282), REAL(-0.724690),
401 REAL(-0.112970), REAL(-0.583097), REAL(-0.707469),
402 REAL(-0.108152), REAL(-0.665375), REAL(-0.700408),
403 REAL(-0.183019), REAL(-0.665378), REAL(-0.717630),
404 REAL(-0.349529), REAL(-0.334459), REAL(-0.511985),
405 REAL(-0.141182), REAL(-0.437705), REAL(-0.798194),
406 REAL(-0.212670), REAL(-0.448725), REAL(-0.737447),
407 REAL(-0.261111), REAL(-0.414945), REAL(-0.613835),
408 REAL(-0.077364), REAL(-0.431480), REAL(-0.778113),
409 REAL(0.005174), REAL(-0.425277), REAL(-0.651592),
410 REAL(0.089236), REAL(-0.431732), REAL(-0.777093),
411 REAL(0.271006), REAL(-0.415749), REAL(-0.610577),
412 REAL(0.223981), REAL(-0.449384), REAL(-0.734774),
413 REAL(0.153275), REAL(-0.438150), REAL(-0.796391),
414 REAL(0.358414), REAL(-0.335529), REAL(-0.507649),
415 REAL(0.193434), REAL(-0.665946), REAL(-0.715325),
416 REAL(0.118363), REAL(-0.665717), REAL(-0.699021),
417 REAL(0.123515), REAL(-0.583454), REAL(-0.706020),
418 REAL(0.196851), REAL(-0.605860), REAL(-0.722345),
419 REAL(0.109788), REAL(-0.516035), REAL(-0.644590),
420 REAL(0.178656), REAL(-0.529656), REAL(-0.652804),
421 REAL(0.061157), REAL(-0.289807), REAL(-0.878626),
422 REAL(0.138234), REAL(-0.293905), REAL(-0.897958),
423 REAL(0.066933), REAL(-0.122643), REAL(-0.943820),
424 REAL(0.149571), REAL(-0.120281), REAL(-0.957264),
425 REAL(0.280989), REAL(-0.280321), REAL(-0.666487),
426 REAL(0.246581), REAL(-0.543275), REAL(-0.584224),
427 REAL(0.211720), REAL(-0.302754), REAL(-0.843303),
428 REAL(0.086966), REAL(-0.665627), REAL(-0.291520),
429 REAL(0.110634), REAL(-0.665702), REAL(-0.185021),
430 REAL(0.228099), REAL(-0.666061), REAL(-0.036201),
431 REAL(0.337743), REAL(-0.666396), REAL(-0.074503),
432 REAL(0.376722), REAL(-0.666513), REAL(-0.219833),
433 REAL(0.377265), REAL(-0.666513), REAL(-0.349036),
434 REAL(0.281411), REAL(-0.666217), REAL(-0.588670),
435 REAL(0.267564), REAL(-0.666174), REAL(-0.654834),
436 REAL(0.080745), REAL(-0.665602), REAL(-0.605452),
437 REAL(0.122016), REAL(-0.662963), REAL(-0.435280),
438 REAL(0.095767), REAL(-0.585141), REAL(-0.607228),
439 REAL(0.118944), REAL(0.012799), REAL(-0.880702),
440 REAL(0.061944), REAL(0.014564), REAL(-0.882086),
441 REAL(0.104725), REAL(0.108156), REAL(-0.949130),
442 REAL(0.048513), REAL(0.115159), REAL(-0.952753),
443 REAL(0.112696), REAL(0.236643), REAL(0.386937),
444 REAL(0.128177), REAL(0.269757), REAL(0.436071),
445 REAL(0.102643), REAL(0.315600), REAL(0.499370),
446 REAL(0.094535), REAL(0.373481), REAL(0.474824),
447 REAL(0.136270), REAL(0.443946), REAL(0.426895),
448 REAL(0.157071), REAL(0.535923), REAL(0.380222),
449 REAL(0.161350), REAL(0.591224), REAL(0.372630),
450 REAL(0.173035), REAL(0.662865), REAL(0.417531),
451 REAL(0.162808), REAL(0.660299), REAL(0.493077),
452 REAL(0.148250), REAL(0.611070), REAL(0.559555),
453 REAL(0.125719), REAL(0.576790), REAL(0.484702),
454 REAL(0.123489), REAL(0.534699), REAL(0.614440),
455 REAL(0.087621), REAL(0.506066), REAL(0.530188),
456 REAL(0.055321), REAL(0.442365), REAL(0.572915),
457 REAL(0.219936), REAL(0.568361), REAL(0.448571),
458 REAL(0.238099), REAL(0.441375), REAL(0.498528),
459 REAL(0.281711), REAL(0.414315), REAL(0.451121),
460 REAL(0.263833), REAL(0.528513), REAL(0.415794),
461 REAL(0.303284), REAL(0.533081), REAL(0.363998),
462 REAL(0.269687), REAL(0.623528), REAL(0.380528),
463 REAL(0.314255), REAL(0.670153), REAL(0.290524),
464 REAL(0.272023), REAL(0.682273), REAL(0.385343),
465 REAL(0.311480), REAL(0.775931), REAL(0.308527),
466 REAL(0.240239), REAL(0.652714), REAL(0.466159),
467 REAL(0.265619), REAL(0.756464), REAL(0.504187),
468 REAL(0.192562), REAL(0.467341), REAL(0.522972),
469 REAL(0.201605), REAL(0.524885), REAL(0.478417),
470 REAL(0.215743), REAL(0.564193), REAL(0.538084),
471 REAL(0.264969), REAL(0.641527), REAL(0.605317),
472 REAL(0.201031), REAL(0.477940), REAL(0.584002),
473 REAL(0.263086), REAL(0.512567), REAL(0.637832),
474 REAL(0.238615), REAL(0.526867), REAL(0.672237),
475 REAL(0.105309), REAL(0.455123), REAL(0.658482),
476 REAL(0.183993), REAL(0.102195), REAL(0.804872),
477 REAL(0.161563), REAL(0.060042), REAL(0.808692),
478 REAL(0.180748), REAL(0.077754), REAL(0.771600),
479 REAL(0.175168), REAL(0.128588), REAL(0.746368),
480 REAL(0.175075), REAL(0.148030), REAL(0.778264),
481 REAL(0.175658), REAL(0.139265), REAL(0.814333),
482 REAL(0.154191), REAL(0.067291), REAL(0.832578),
483 REAL(0.163818), REAL(0.109013), REAL(0.842830),
484 REAL(0.084760), REAL(0.396004), REAL(0.679695),
485 REAL(0.238888), REAL(0.310760), REAL(0.590775),
486 REAL(0.213380), REAL(0.308625), REAL(0.644905),
487 REAL(0.199666), REAL(0.409678), REAL(0.683003),
488 REAL(0.190143), REAL(0.128597), REAL(0.733463),
489 REAL(0.184833), REAL(0.063516), REAL(0.762902),
490 REAL(0.166070), REAL(0.035644), REAL(0.818261),
491 REAL(0.154361), REAL(0.056943), REAL(0.857042),
492 REAL(0.168542), REAL(0.109489), REAL(0.862725),
493 REAL(0.187387), REAL(0.166131), REAL(0.784599),
494 REAL(0.180428), REAL(0.160135), REAL(0.819438),
495 REAL(0.201823), REAL(0.163991), REAL(0.695756),
496 REAL(0.194206), REAL(0.206635), REAL(0.782275),
497 REAL(0.155438), REAL(0.291260), REAL(0.734412),
498 REAL(0.177696), REAL(0.196424), REAL(0.846693),
499 REAL(0.152305), REAL(0.125256), REAL(0.890786),
500 REAL(0.119546), REAL(0.249876), REAL(0.859104),
501 REAL(0.118369), REAL(0.139643), REAL(0.919173),
502 REAL(0.079410), REAL(0.132973), REAL(0.948652),
503 REAL(0.062419), REAL(0.036648), REAL(0.976547),
504 REAL(0.127847), REAL(-0.035919), REAL(0.947070),
505 REAL(0.143624), REAL(0.032206), REAL(0.885913),
506 REAL(0.074888), REAL(-0.085173), REAL(0.980577),
507 REAL(0.130184), REAL(-0.104656), REAL(0.947620),
508 REAL(0.156201), REAL(-0.094653), REAL(0.899074),
509 REAL(0.077366), REAL(-0.171194), REAL(0.926545),
510 REAL(0.127722), REAL(-0.164729), REAL(0.879810),
511 REAL(0.052670), REAL(-0.184618), REAL(0.842019),
512 REAL(0.023477), REAL(-0.184638), REAL(0.889811),
513 REAL(0.022626), REAL(-0.210587), REAL(0.827500),
514 REAL(0.223089), REAL(0.211976), REAL(0.620493),
515 REAL(0.251444), REAL(0.113067), REAL(0.666494),
516 REAL(0.251419), REAL(0.089540), REAL(0.673887),
517 REAL(0.214360), REAL(0.019258), REAL(0.771595),
518 REAL(0.158999), REAL(0.001490), REAL(0.835374),
519 REAL(0.176696), REAL(-0.059249), REAL(0.849218),
520 REAL(0.148696), REAL(-0.130091), REAL(0.793599),
521 REAL(0.108290), REAL(-0.166528), REAL(0.772088),
522 REAL(0.049820), REAL(-0.201382), REAL(0.764454),
523 REAL(0.071341), REAL(-0.215195), REAL(0.697209),
524 REAL(0.073148), REAL(-0.214475), REAL(0.623510),
525 REAL(0.140502), REAL(-0.169461), REAL(0.699354),
526 REAL(0.163374), REAL(-0.157073), REAL(0.611416),
527 REAL(0.189466), REAL(-0.138550), REAL(0.730366),
528 REAL(0.247593), REAL(-0.082554), REAL(0.759610),
529 REAL(0.227468), REAL(-0.121982), REAL(0.590197),
530 REAL(0.284702), REAL(-0.006586), REAL(0.535347),
531 REAL(0.275741), REAL(0.125287), REAL(0.446676),
532 REAL(0.266650), REAL(0.192594), REAL(0.506044),
533 REAL(0.300086), REAL(0.053287), REAL(0.629620),
534 REAL(0.055450), REAL(-0.663935), REAL(0.375065),
535 REAL(0.122854), REAL(-0.664138), REAL(0.482323),
536 REAL(0.046520), REAL(-0.531571), REAL(0.391918),
537 REAL(0.024824), REAL(-0.568450), REAL(0.275106),
538 REAL(0.053855), REAL(-0.663931), REAL(0.328224),
539 REAL(0.112829), REAL(-0.453549), REAL(0.305788),
540 REAL(0.131265), REAL(-0.510617), REAL(0.080746),
541 REAL(0.061174), REAL(-0.430716), REAL(-0.042710),
542 REAL(0.341019), REAL(-0.532887), REAL(-0.208150),
543 REAL(0.347705), REAL(-0.623533), REAL(-0.081139),
544 REAL(0.238040), REAL(-0.610732), REAL(-0.038037),
545 REAL(0.211764), REAL(-0.514274), REAL(-0.132078),
546 REAL(0.120605), REAL(-0.600219), REAL(-0.186856),
547 REAL(0.096985), REAL(-0.584476), REAL(-0.293357),
548 REAL(0.127621), REAL(-0.581941), REAL(-0.437170),
549 REAL(0.165902), REAL(-0.477425), REAL(-0.291453),
550 REAL(0.077720), REAL(-0.417975), REAL(-0.220519),
551 REAL(0.320892), REAL(-0.506363), REAL(-0.320874),
552 REAL(0.248214), REAL(-0.465684), REAL(-0.239842),
553 REAL(0.118764), REAL(-0.383338), REAL(-0.187114),
554 REAL(0.118816), REAL(-0.430106), REAL(-0.123307),
555 REAL(0.094131), REAL(-0.419464), REAL(-0.044777),
556 REAL(0.274526), REAL(-0.261706), REAL(0.005110),
557 REAL(0.259842), REAL(-0.283292), REAL(-0.003185),
558 REAL(0.222861), REAL(-0.340431), REAL(-0.038210),
559 REAL(0.204445), REAL(-0.664380), REAL(0.513353),
560 REAL(0.259286), REAL(-0.664547), REAL(0.471281),
561 REAL(0.185402), REAL(-0.476020), REAL(0.421718),
562 REAL(0.279163), REAL(-0.664604), REAL(0.417328),
563 REAL(0.277157), REAL(-0.528122), REAL(0.400208),
564 REAL(0.183069), REAL(-0.509812), REAL(0.329995),
565 REAL(0.282599), REAL(-0.429210), REAL(0.059242),
566 REAL(0.254816), REAL(-0.664541), REAL(0.290687),
567 REAL(0.271436), REAL(-0.567707), REAL(0.263966),
568 REAL(0.386561), REAL(-0.625221), REAL(-0.216870),
569 REAL(0.387086), REAL(-0.630883), REAL(-0.346073),
570 REAL(0.380021), REAL(-0.596021), REAL(-0.318679),
571 REAL(0.291269), REAL(-0.619007), REAL(-0.585707),
572 REAL(0.339280), REAL(-0.571198), REAL(-0.461946),
573 REAL(0.400045), REAL(-0.489778), REAL(-0.422640),
574 REAL(0.406817), REAL(-0.314349), REAL(-0.371230),
575 REAL(0.300588), REAL(-0.281718), REAL(-0.170549),
576 REAL(0.290866), REAL(-0.277304), REAL(-0.061905),
577 REAL(0.187735), REAL(-0.241545), REAL(0.509437),
578 REAL(0.188032), REAL(-0.287569), REAL(0.424234),
579 REAL(0.227520), REAL(-0.373262), REAL(0.293102),
580 REAL(0.266526), REAL(-0.273650), REAL(0.039597),
581 REAL(0.291592), REAL(-0.291676), REAL(0.111386),
582 REAL(0.291914), REAL(-0.122741), REAL(0.422683),
583 REAL(0.297574), REAL(-0.156119), REAL(0.373368),
584 REAL(0.286603), REAL(-0.232731), REAL(0.027162),
585 REAL(0.364663), REAL(-0.201399), REAL(0.206850),
586 REAL(0.353855), REAL(-0.132408), REAL(0.149228),
587 REAL(0.282208), REAL(-0.019715), REAL(0.314960),
588 REAL(0.331187), REAL(-0.099266), REAL(0.092701),
589 REAL(0.375463), REAL(-0.093120), REAL(-0.006467),
590 REAL(0.375917), REAL(-0.101236), REAL(-0.154882),
591 REAL(0.466635), REAL(-0.094416), REAL(-0.305669),
592 REAL(0.455805), REAL(-0.119881), REAL(-0.460632),
593 REAL(0.277465), REAL(-0.604242), REAL(-0.651871),
594 REAL(0.261022), REAL(-0.551176), REAL(-0.554667),
595 REAL(0.093627), REAL(0.258494), REAL(-0.920589),
596 REAL(0.114248), REAL(0.310608), REAL(-0.798070),
597 REAL(0.144232), REAL(0.211434), REAL(-0.835001),
598 REAL(0.119916), REAL(0.176940), REAL(-0.951159),
599 REAL(0.184061), REAL(0.101854), REAL(-0.918220),
600 REAL(0.092431), REAL(0.276521), REAL(-0.738231),
601 REAL(0.133504), REAL(0.218403), REAL(-0.758602),
602 REAL(0.194987), REAL(0.097655), REAL(-0.812476),
603 REAL(0.185542), REAL(0.011005), REAL(-0.879202),
604 REAL(0.230315), REAL(-0.127450), REAL(-0.884202),
605 REAL(0.260471), REAL(0.255056), REAL(-0.624378),
606 REAL(0.351567), REAL(-0.042194), REAL(-0.663976),
607 REAL(0.253742), REAL(0.323524), REAL(-0.433716),
608 REAL(0.411612), REAL(0.132299), REAL(-0.438264),
609 REAL(0.270513), REAL(0.356530), REAL(-0.289984),
610 REAL(0.422146), REAL(0.162819), REAL(-0.273130),
611 REAL(0.164724), REAL(0.237490), REAL(0.208912),
612 REAL(0.253806), REAL(0.092900), REAL(0.240640),
613 REAL(0.203608), REAL(0.284597), REAL(0.096223),
614 REAL(0.241006), REAL(0.343093), REAL(-0.171396),
615 REAL(0.356076), REAL(0.149288), REAL(-0.143443),
616 REAL(0.337656), REAL(0.131992), REAL(0.066374)
617};
618
619int Indices[IndexCount / 3][3] = {
620 {126,134,133},
621 {342,138,134},
622 {133,134,138},
623 {126,342,134},
624 {312,316,317},
625 {169,163,162},
626 {312,317,319},
627 {312,319,318},
628 {169,162,164},
629 {169,168,163},
630 {312,314,315},
631 {169,164,165},
632 {169,167,168},
633 {312,315,316},
634 {312,313,314},
635 {169,165,166},
636 {169,166,167},
637 {312,318,313},
638 {308,304,305},
639 {308,305,306},
640 {179,181,188},
641 {177,173,175},
642 {177,175,176},
643 {302,293,300},
644 {322,294,304},
645 {188,176,175},
646 {188,175,179},
647 {158,177,187},
648 {305,293,302},
649 {305,302,306},
650 {322,304,308},
651 {188,181,183},
652 {158,173,177},
653 {293,298,300},
654 {304,294,296},
655 {304,296,305},
656 {185,176,188},
657 {185,188,183},
658 {187,177,176},
659 {187,176,185},
660 {305,296,298},
661 {305,298,293},
662 {436,432, 28},
663 {436, 28, 23},
664 {434,278,431},
665 { 30,208,209},
666 { 30,209, 29},
667 { 19, 20, 24},
668 {208,207,211},
669 {208,211,209},
670 { 19,210,212},
671 {433,434,431},
672 {433,431,432},
673 {433,432,436},
674 {436,437,433},
675 {277,275,276},
676 {277,276,278},
677 {209,210, 25},
678 { 21, 26, 24},
679 { 21, 24, 20},
680 { 25, 26, 27},
681 { 25, 27, 29},
682 {435,439,277},
683 {439,275,277},
684 {432,431, 30},
685 {432, 30, 28},
686 {433,437,438},
687 {433,438,435},
688 {434,277,278},
689 { 24, 25,210},
690 { 24, 26, 25},
691 { 29, 27, 28},
692 { 29, 28, 30},
693 { 19, 24,210},
694 {208, 30,431},
695 {208,431,278},
696 {435,434,433},
697 {435,277,434},
698 { 25, 29,209},
699 { 27, 22, 23},
700 { 27, 23, 28},
701 { 26, 22, 27},
702 { 26, 21, 22},
703 {212,210,209},
704 {212,209,211},
705 {207,208,278},
706 {207,278,276},
707 {439,435,438},
708 { 12, 9, 10},
709 { 12, 10, 13},
710 { 2, 3, 5},
711 { 2, 5, 4},
712 { 16, 13, 14},
713 { 16, 14, 17},
714 { 22, 21, 16},
715 { 13, 10, 11},
716 { 13, 11, 14},
717 { 1, 0, 3},
718 { 1, 3, 2},
719 { 15, 12, 16},
720 { 19, 18, 15},
721 { 19, 15, 16},
722 { 19, 16, 20},
723 { 9, 1, 2},
724 { 9, 2, 10},
725 { 3, 7, 8},
726 { 3, 8, 5},
727 { 16, 17, 23},
728 { 16, 23, 22},
729 { 21, 20, 16},
730 { 10, 2, 4},
731 { 10, 4, 11},
732 { 0, 6, 7},
733 { 0, 7, 3},
734 { 12, 13, 16},
735 {451,446,445},
736 {451,445,450},
737 {442,440,439},
738 {442,439,438},
739 {442,438,441},
740 {421,420,422},
741 {412,411,426},
742 {412,426,425},
743 {408,405,407},
744 {413, 67, 68},
745 {413, 68,414},
746 {391,390,412},
747 { 80,384,386},
748 {404,406,378},
749 {390,391,377},
750 {390,377, 88},
751 {400,415,375},
752 {398,396,395},
753 {398,395,371},
754 {398,371,370},
755 {112,359,358},
756 {112,358,113},
757 {351,352,369},
758 {125,349,348},
759 {345,343,342},
760 {342,340,339},
761 {341,335,337},
762 {328,341,327},
763 {331,323,333},
764 {331,322,323},
765 {327,318,319},
766 {327,319,328},
767 {315,314,324},
768 {302,300,301},
769 {302,301,303},
770 {320,311,292},
771 {285,284,289},
772 {310,307,288},
773 {310,288,290},
774 {321,350,281},
775 {321,281,282},
776 {423,448,367},
777 {272,273,384},
778 {272,384,274},
779 {264,265,382},
780 {264,382,383},
781 {440,442,261},
782 {440,261,263},
783 {252,253,254},
784 {252,254,251},
785 {262,256,249},
786 {262,249,248},
787 {228,243,242},
788 {228, 31,243},
789 {213,215,238},
790 {213,238,237},
791 { 19,212,230},
792 {224,225,233},
793 {224,233,231},
794 {217,218, 56},
795 {217, 56, 54},
796 {217,216,239},
797 {217,239,238},
798 {217,238,215},
799 {218,217,215},
800 {218,215,214},
801 { 6,102,206},
802 {186,199,200},
803 {197,182,180},
804 {170,171,157},
805 {201,200,189},
806 {170,190,191},
807 {170,191,192},
808 {175,174,178},
809 {175,178,179},
810 {168,167,155},
811 {122,149,158},
812 {122,158,159},
813 {135,153,154},
814 {135,154,118},
815 {143,140,141},
816 {143,141,144},
817 {132,133,136},
818 {130,126,133},
819 {124,125,127},
820 {122,101,100},
821 {122,100,121},
822 {110,108,107},
823 {110,107,109},
824 { 98, 99, 97},
825 { 98, 97, 64},
826 { 98, 64, 66},
827 { 87, 55, 57},
828 { 83, 82, 79},
829 { 83, 79, 84},
830 { 78, 74, 50},
831 { 49, 71, 41},
832 { 49, 41, 37},
833 { 49, 37, 36},
834 { 58, 44, 60},
835 { 60, 59, 58},
836 { 51, 34, 33},
837 { 39, 40, 42},
838 { 39, 42, 38},
839 {243,240, 33},
840 {243, 33,229},
841 { 39, 38, 6},
842 { 44, 46, 40},
843 { 55, 56, 57},
844 { 64, 62, 65},
845 { 64, 65, 66},
846 { 41, 71, 45},
847 { 75, 50, 51},
848 { 81, 79, 82},
849 { 77, 88, 73},
850 { 93, 92, 94},
851 { 68, 47, 46},
852 { 96, 97, 99},
853 { 96, 99, 95},
854 {110,109,111},
855 {111,112,110},
856 {114,113,123},
857 {114,123,124},
858 {132,131,129},
859 {133,137,136},
860 {135,142,145},
861 {145,152,135},
862 {149,147,157},
863 {157,158,149},
864 {164,150,151},
865 {153,163,168},
866 {153,168,154},
867 {185,183,182},
868 {185,182,184},
869 {161,189,190},
870 {200,199,191},
871 {200,191,190},
872 {180,178,195},
873 {180,195,196},
874 {102,101,204},
875 {102,204,206},
876 { 43, 48,104},
877 { 43,104,103},
878 {216,217, 54},
879 {216, 54, 32},
880 {207,224,231},
881 {230,212,211},
882 {230,211,231},
883 {227,232,241},
884 {227,241,242},
885 {235,234,241},
886 {235,241,244},
887 {430,248,247},
888 {272,274,253},
889 {272,253,252},
890 {439,260,275},
891 {225,224,259},
892 {225,259,257},
893 {269,270,407},
894 {269,407,405},
895 {270,269,273},
896 {270,273,272},
897 {273,269,268},
898 {273,268,267},
899 {273,267,266},
900 {273,266,265},
901 {273,265,264},
902 {448,279,367},
903 {281,350,368},
904 {285,286,301},
905 {290,323,310},
906 {290,311,323},
907 {282,281,189},
908 {292,311,290},
909 {292,290,291},
910 {307,306,302},
911 {307,302,303},
912 {316,315,324},
913 {316,324,329},
914 {331,351,350},
915 {330,334,335},
916 {330,335,328},
917 {341,337,338},
918 {344,355,354},
919 {346,345,348},
920 {346,348,347},
921 {364,369,352},
922 {364,352,353},
923 {365,363,361},
924 {365,361,362},
925 {376,401,402},
926 {373,372,397},
927 {373,397,400},
928 {376, 92,377},
929 {381,378,387},
930 {381,387,385},
931 {386, 77, 80},
932 {390,389,412},
933 {416,417,401},
934 {403,417,415},
935 {408,429,430},
936 {419,423,418},
937 {427,428,444},
938 {427,444,446},
939 {437,436,441},
940 {450,445, 11},
941 {450, 11, 4},
942 {447,449, 5},
943 {447, 5, 8},
944 {441,438,437},
945 {425,426,451},
946 {425,451,452},
947 {417,421,415},
948 {408,407,429},
949 {399,403,400},
950 {399,400,397},
951 {394,393,416},
952 {389,411,412},
953 {386,383,385},
954 {408,387,378},
955 {408,378,406},
956 {377,391,376},
957 { 94,375,415},
958 {372,373,374},
959 {372,374,370},
960 {359,111,360},
961 {359,112,111},
962 {113,358,349},
963 {113,349,123},
964 {346,343,345},
965 {343,340,342},
966 {338,336,144},
967 {338,144,141},
968 {327,341,354},
969 {327,354,326},
970 {331,350,321},
971 {331,321,322},
972 {314,313,326},
973 {314,326,325},
974 {300,298,299},
975 {300,299,301},
976 {288,287,289},
977 {189,292,282},
978 {287,288,303},
979 {284,285,297},
980 {368,280,281},
981 {448,447,279},
982 {274,226,255},
983 {267,268,404},
984 {267,404,379},
985 {429,262,430},
986 {439,440,260},
987 {257,258,249},
988 {257,249,246},
989 {430,262,248},
990 {234,228,242},
991 {234,242,241},
992 {237,238,239},
993 {237,239,236},
994 { 15, 18,227},
995 { 15,227,229},
996 {222,223, 82},
997 {222, 82, 83},
998 {214,215,213},
999 {214,213, 81},
1000 { 38,102, 6},
1001 {122,159,200},
1002 {122,200,201},
1003 {174,171,192},
1004 {174,192,194},
1005 {197,193,198},
1006 {190,170,161},
1007 {181,179,178},
1008 {181,178,180},
1009 {166,156,155},
1010 {163,153,152},
1011 {163,152,162},
1012 {120,156,149},
1013 {120,149,121},
1014 {152,153,135},
1015 {140,143,142},
1016 {135,131,132},
1017 {135,132,136},
1018 {130,129,128},
1019 {130,128,127},
1020 {100,105,119},
1021 {100,119,120},
1022 {106,104,107},
1023 {106,107,108},
1024 { 91, 95, 59},
1025 { 93, 94, 68},
1026 { 91, 89, 92},
1027 { 76, 53, 55},
1028 { 76, 55, 87},
1029 { 81, 78, 79},
1030 { 74, 73, 49},
1031 { 69, 60, 45},
1032 { 58, 62, 64},
1033 { 58, 64, 61},
1034 { 53, 31, 32},
1035 { 32, 54, 53},
1036 { 42, 43, 38},
1037 { 35, 36, 0},
1038 { 35, 0, 1},
1039 { 34, 35, 1},
1040 { 34, 1, 9},
1041 { 44, 40, 41},
1042 { 44, 41, 45},
1043 { 33,240, 51},
1044 { 63, 62, 58},
1045 { 63, 58, 59},
1046 { 45, 71, 70},
1047 { 76, 75, 51},
1048 { 76, 51, 52},
1049 { 86, 85, 84},
1050 { 86, 84, 87},
1051 { 89, 72, 73},
1052 { 89, 73, 88},
1053 { 91, 92, 96},
1054 { 91, 96, 95},
1055 { 72, 91, 60},
1056 { 72, 60, 69},
1057 {104,106,105},
1058 {119,105,117},
1059 {119,117,118},
1060 {124,127,128},
1061 {117,116,129},
1062 {117,129,131},
1063 {118,117,131},
1064 {135,140,142},
1065 {146,150,152},
1066 {146,152,145},
1067 {149,122,121},
1068 {166,165,151},
1069 {166,151,156},
1070 {158,172,173},
1071 {161,160,189},
1072 {199,198,193},
1073 {199,193,191},
1074 {204,201,202},
1075 {178,174,194},
1076 {200,159,186},
1077 {109, 48, 67},
1078 { 48,107,104},
1079 {216, 32,236},
1080 {216,236,239},
1081 {223,214, 81},
1082 {223, 81, 82},
1083 { 33, 12, 15},
1084 { 32,228,234},
1085 { 32,234,236},
1086 {240, 31, 52},
1087 {256,255,246},
1088 {256,246,249},
1089 {258,263,248},
1090 {258,248,249},
1091 {275,260,259},
1092 {275,259,276},
1093 {207,276,259},
1094 {270,271,429},
1095 {270,429,407},
1096 {413,418,366},
1097 {413,366,365},
1098 {368,367,279},
1099 {368,279,280},
1100 {303,301,286},
1101 {303,286,287},
1102 {283,282,292},
1103 {283,292,291},
1104 {320,292,189},
1105 {298,296,297},
1106 {298,297,299},
1107 {318,327,326},
1108 {318,326,313},
1109 {329,330,317},
1110 {336,333,320},
1111 {326,354,353},
1112 {334,332,333},
1113 {334,333,336},
1114 {342,339,139},
1115 {342,139,138},
1116 {345,342,126},
1117 {347,357,356},
1118 {369,368,351},
1119 {363,356,357},
1120 {363,357,361},
1121 {366,367,368},
1122 {366,368,369},
1123 {375,373,400},
1124 { 92, 90,377},
1125 {409,387,408},
1126 {386,385,387},
1127 {386,387,388},
1128 {412,394,391},
1129 {396,398,399},
1130 {408,406,405},
1131 {415,421,419},
1132 {415,419,414},
1133 {425,452,448},
1134 {425,448,424},
1135 {444,441,443},
1136 {448,452,449},
1137 {448,449,447},
1138 {446,444,443},
1139 {446,443,445},
1140 {250,247,261},
1141 {250,261,428},
1142 {421,422,423},
1143 {421,423,419},
1144 {427,410,250},
1145 {417,403,401},
1146 {403,402,401},
1147 {420,392,412},
1148 {420,412,425},
1149 {420,425,424},
1150 {386,411,389},
1151 {383,382,381},
1152 {383,381,385},
1153 {378,379,404},
1154 {372,371,395},
1155 {372,395,397},
1156 {371,372,370},
1157 {361,359,360},
1158 {361,360,362},
1159 {368,350,351},
1160 {349,347,348},
1161 {356,355,344},
1162 {356,344,346},
1163 {344,341,340},
1164 {344,340,343},
1165 {338,337,336},
1166 {328,335,341},
1167 {324,352,351},
1168 {324,351,331},
1169 {320,144,336},
1170 {314,325,324},
1171 {322,308,309},
1172 {310,309,307},
1173 {287,286,289},
1174 {203,280,279},
1175 {203,279,205},
1176 {297,295,283},
1177 {297,283,284},
1178 {447,205,279},
1179 {274,384, 80},
1180 {274, 80,226},
1181 {266,267,379},
1182 {266,379,380},
1183 {225,257,246},
1184 {225,246,245},
1185 {256,254,253},
1186 {256,253,255},
1187 {430,247,250},
1188 {226,235,244},
1189 {226,244,245},
1190 {232,233,244},
1191 {232,244,241},
1192 {230, 18, 19},
1193 { 32, 31,228},
1194 {219,220, 86},
1195 {219, 86, 57},
1196 {226,213,235},
1197 {206, 7, 6},
1198 {122,201,101},
1199 {201,204,101},
1200 {180,196,197},
1201 {170,192,171},
1202 {200,190,189},
1203 {194,193,195},
1204 {183,181,180},
1205 {183,180,182},
1206 {155,154,168},
1207 {149,156,151},
1208 {149,151,148},
1209 {155,156,120},
1210 {145,142,143},
1211 {145,143,146},
1212 {136,137,140},
1213 {133,132,130},
1214 {128,129,116},
1215 {100,120,121},
1216 {110,112,113},
1217 {110,113,114},
1218 { 66, 65, 63},
1219 { 66, 63, 99},
1220 { 66, 99, 98},
1221 { 96, 46, 61},
1222 { 89, 88, 90},
1223 { 86, 87, 57},
1224 { 80, 78, 81},
1225 { 72, 69, 49},
1226 { 67, 48, 47},
1227 { 67, 47, 68},
1228 { 56, 55, 53},
1229 { 50, 49, 36},
1230 { 50, 36, 35},
1231 { 40, 39, 41},
1232 {242,243,229},
1233 {242,229,227},
1234 { 6, 37, 39},
1235 { 42, 47, 48},
1236 { 42, 48, 43},
1237 { 61, 46, 44},
1238 { 45, 70, 69},
1239 { 69, 70, 71},
1240 { 69, 71, 49},
1241 { 74, 78, 77},
1242 { 83, 84, 85},
1243 { 73, 74, 77},
1244 { 93, 96, 92},
1245 { 68, 46, 93},
1246 { 95, 99, 63},
1247 { 95, 63, 59},
1248 {115,108,110},
1249 {115,110,114},
1250 {125,126,127},
1251 {129,130,132},
1252 {137,133,138},
1253 {137,138,139},
1254 {148,146,143},
1255 {148,143,147},
1256 {119,118,154},
1257 {161,147,143},
1258 {165,164,151},
1259 {158,157,171},
1260 {158,171,172},
1261 {159,158,187},
1262 {159,187,186},
1263 {194,192,191},
1264 {194,191,193},
1265 {189,202,201},
1266 {182,197,184},
1267 {205, 8, 7},
1268 { 48,109,107},
1269 {218,219, 57},
1270 {218, 57, 56},
1271 {207,231,211},
1272 {232,230,231},
1273 {232,231,233},
1274 { 53, 52, 31},
1275 {388,411,386},
1276 {409,430,250},
1277 {262,429,254},
1278 {262,254,256},
1279 {442,444,428},
1280 {273,264,383},
1281 {273,383,384},
1282 {429,271,251},
1283 {429,251,254},
1284 {413,365,362},
1285 { 67,413,360},
1286 {282,283,295},
1287 {285,301,299},
1288 {202,281,280},
1289 {284,283,291},
1290 {284,291,289},
1291 {320,189,160},
1292 {308,306,307},
1293 {307,309,308},
1294 {319,317,330},
1295 {319,330,328},
1296 {353,352,324},
1297 {332,331,333},
1298 {340,341,338},
1299 {354,341,344},
1300 {349,358,357},
1301 {349,357,347},
1302 {364,355,356},
1303 {364,356,363},
1304 {364,365,366},
1305 {364,366,369},
1306 {374,376,402},
1307 {375, 92,373},
1308 { 77,389,390},
1309 {382,380,381},
1310 {389, 77,386},
1311 {393,394,412},
1312 {393,412,392},
1313 {401,394,416},
1314 {415,400,403},
1315 {411,410,427},
1316 {411,427,426},
1317 {422,420,424},
1318 {247,248,263},
1319 {247,263,261},
1320 {445,443, 14},
1321 {445, 14, 11},
1322 {449,450, 4},
1323 {449, 4, 5},
1324 {443,441, 17},
1325 {443, 17, 14},
1326 {436, 23, 17},
1327 {436, 17,441},
1328 {424,448,422},
1329 {448,423,422},
1330 {414,419,418},
1331 {414,418,413},
1332 {406,404,405},
1333 {399,397,395},
1334 {399,395,396},
1335 {420,416,392},
1336 {388,410,411},
1337 {386,384,383},
1338 {390, 88, 77},
1339 {375, 94, 92},
1340 {415,414, 68},
1341 {415, 68, 94},
1342 {370,374,402},
1343 {370,402,398},
1344 {361,357,358},
1345 {361,358,359},
1346 {125,348,126},
1347 {346,344,343},
1348 {340,338,339},
1349 {337,335,334},
1350 {337,334,336},
1351 {325,353,324},
1352 {324,331,332},
1353 {324,332,329},
1354 {323,322,309},
1355 {323,309,310},
1356 {294,295,297},
1357 {294,297,296},
1358 {289,286,285},
1359 {202,280,203},
1360 {288,307,303},
1361 {282,295,321},
1362 { 67,360,111},
1363 {418,423,367},
1364 {418,367,366},
1365 {272,252,251},
1366 {272,251,271},
1367 {272,271,270},
1368 {255,253,274},
1369 {265,266,380},
1370 {265,380,382},
1371 {442,428,261},
1372 {440,263,258},
1373 {440,258,260},
1374 {409,250,410},
1375 {255,226,245},
1376 {255,245,246},
1377 { 31,240,243},
1378 {236,234,235},
1379 {236,235,237},
1380 {233,225,245},
1381 {233,245,244},
1382 {220,221, 85},
1383 {220, 85, 86},
1384 { 81,213,226},
1385 { 81,226, 80},
1386 { 7,206,205},
1387 {186,184,198},
1388 {186,198,199},
1389 {204,203,205},
1390 {204,205,206},
1391 {195,193,196},
1392 {171,174,172},
1393 {173,174,175},
1394 {173,172,174},
1395 {155,167,166},
1396 {160,161,143},
1397 {160,143,144},
1398 {119,154,155},
1399 {148,151,150},
1400 {148,150,146},
1401 {140,137,139},
1402 {140,139,141},
1403 {127,126,130},
1404 {114,124,128},
1405 {114,128,115},
1406 {117,105,106},
1407 {117,106,116},
1408 {104,105,100},
1409 {104,100,103},
1410 { 59, 60, 91},
1411 { 97, 96, 61},
1412 { 97, 61, 64},
1413 { 91, 72, 89},
1414 { 87, 84, 79},
1415 { 87, 79, 76},
1416 { 78, 80, 77},
1417 { 49, 50, 74},
1418 { 60, 44, 45},
1419 { 61, 44, 58},
1420 { 51, 50, 35},
1421 { 51, 35, 34},
1422 { 39, 37, 41},
1423 { 33, 34, 9},
1424 { 33, 9, 12},
1425 { 0, 36, 37},
1426 { 0, 37, 6},
1427 { 40, 46, 47},
1428 { 40, 47, 42},
1429 { 53, 54, 56},
1430 { 65, 62, 63},
1431 { 72, 49, 73},
1432 { 79, 78, 75},
1433 { 79, 75, 76},
1434 { 52, 53, 76},
1435 { 92, 89, 90},
1436 { 96, 93, 46},
1437 {102,103,100},
1438 {102,100,101},
1439 {116,106,108},
1440 {116,108,115},
1441 {123,125,124},
1442 {116,115,128},
1443 {118,131,135},
1444 {140,135,136},
1445 {148,147,149},
1446 {120,119,155},
1447 {164,162,152},
1448 {164,152,150},
1449 {157,147,161},
1450 {157,161,170},
1451 {186,187,185},
1452 {186,185,184},
1453 {193,197,196},
1454 {202,203,204},
1455 {194,195,178},
1456 {198,184,197},
1457 { 67,111,109},
1458 { 38, 43,103},
1459 { 38,103,102},
1460 {214,223,222},
1461 {214,222,221},
1462 {214,221,220},
1463 {214,220,219},
1464 {214,219,218},
1465 {213,237,235},
1466 {221,222, 83},
1467 {221, 83, 85},
1468 { 15,229, 33},
1469 {227, 18,230},
1470 {227,230,232},
1471 { 52, 51,240},
1472 { 75, 78, 50},
1473 {408,430,409},
1474 {260,258,257},
1475 {260,257,259},
1476 {224,207,259},
1477 {268,269,405},
1478 {268,405,404},
1479 {413,362,360},
1480 {447, 8,205},
1481 {299,297,285},
1482 {189,281,202},
1483 {290,288,289},
1484 {290,289,291},
1485 {322,321,295},
1486 {322,295,294},
1487 {333,323,311},
1488 {333,311,320},
1489 {317,316,329},
1490 {320,160,144},
1491 {353,325,326},
1492 {329,332,334},
1493 {329,334,330},
1494 {339,338,141},
1495 {339,141,139},
1496 {348,345,126},
1497 {347,356,346},
1498 {123,349,125},
1499 {364,353,354},
1500 {364,354,355},
1501 {365,364,363},
1502 {376,391,394},
1503 {376,394,401},
1504 { 92,376,374},
1505 { 92,374,373},
1506 {377, 90, 88},
1507 {380,379,378},
1508 {380,378,381},
1509 {388,387,409},
1510 {388,409,410},
1511 {416,393,392},
1512 {399,398,402},
1513 {399,402,403},
1514 {250,428,427},
1515 {421,417,416},
1516 {421,416,420},
1517 {426,427,446},
1518 {426,446,451},
1519 {444,442,441},
1520 {452,451,450},
1521 {452,450,449}
1522};
1523
1524//============================
1525
1526
1527dReal heightfield_callback( void* pUserData, int x, int z )
1528{
1529 dIASSERT( x < HFIELD_WSTEP );
1530 dIASSERT( z < HFIELD_DSTEP );
1531
1532 dReal fx = ( ((dReal)x) - ( HFIELD_WSTEP-1 )/2 ) / (dReal)( HFIELD_WSTEP-1 );
1533 dReal fz = ( ((dReal)z) - ( HFIELD_DSTEP-1 )/2 ) / (dReal)( HFIELD_DSTEP-1 );
1534
1535 // Create an interesting 'hump' shape
1536 dReal h = REAL( 1.0 ) + ( REAL( -16.0 ) * ( fx*fx*fx + fz*fz*fz ) );
1537
1538 return h;
1539}
1540
1541
1542
1543
1544
1545// this is called by dSpaceCollide when two objects in space are
1546// potentially colliding.
1547
1548static void nearCallback (void *data, dGeomID o1, dGeomID o2)
1549{
1550 int i;
1551 // if (o1->body && o2->body) return;
1552
1553 // exit without doing anything if the two bodies are connected by a joint
1554 dBodyID b1 = dGeomGetBody(o1);
1555 dBodyID b2 = dGeomGetBody(o2);
1556 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
1557
1558 dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
1559 for (i=0; i<MAX_CONTACTS; i++) {
1560 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
1561 contact[i].surface.mu = dInfinity;
1562 contact[i].surface.mu2 = 0;
1563 contact[i].surface.bounce = 0.1;
1564 contact[i].surface.bounce_vel = 0.1;
1565 contact[i].surface.soft_cfm = 0.01;
1566 }
1567 if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
1568 sizeof(dContact))) {
1569 dMatrix3 RI;
1570 dRSetIdentity (RI);
1571 const dReal ss[3] = {0.02,0.02,0.02};
1572 for (i=0; i<numc; i++) {
1573 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
1574 dJointAttach (c,b1,b2);
1575 if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
1576 }
1577 }
1578}
1579
1580
1581// start simulation - set viewpoint
1582
1583static void start()
1584{
1585 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
1586 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
1587 dsSetViewpoint (xyz,hpr);
1588 printf ("To drop another object, press:\n");
1589 printf (" b for box.\n");
1590 printf (" s for sphere.\n");
1591 printf (" c for capsule.\n");
1592 printf (" y for cylinder.\n");
1593 printf (" v for a convex object.\n");
1594 printf (" x for a composite object.\n");
1595 printf (" m for a trimesh.\n");
1596 printf ("To select an object, press space.\n");
1597 printf ("To disable the selected object, press d.\n");
1598 printf ("To enable the selected object, press e.\n");
1599 printf ("To toggle showing the geom AABBs, press a.\n");
1600 printf ("To toggle showing the contact points, press t.\n");
1601 printf ("To toggle dropping from random position/orientation, press r.\n");
1602 printf ("To save the current state to 'state.dif', press 1.\n");
1603}
1604
1605
1606char locase (char c)
1607{
1608 if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
1609 else return c;
1610}
1611
1612
1613// called when a key pressed
1614
1615static void command (int cmd)
1616{
1617 size_t i;
1618 int j,k;
1619 dReal sides[3];
1620 dMass m;
1621
1622 cmd = locase (cmd);
1623
1624
1625 //
1626 // Geom Creation
1627 //
1628
1629 if ( cmd == 'b' || cmd == 's' || cmd == 'c' ||
1630 cmd == 'x' || cmd == 'y' || cmd == 'm' || cmd == 'v' )
1631 {
1632 if ( num < NUM )
1633 {
1634 i = num;
1635 num++;
1636 }
1637 else
1638 {
1639 i = nextobj;
1640 nextobj++;
1641 if (nextobj >= num) nextobj = 0;
1642
1643 // destroy the body and geoms for slot i
1644 dBodyDestroy (obj[i].body);
1645 for (k=0; k < GPB; k++)
1646 {
1647 if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
1648 }
1649 memset (&obj[i],0,sizeof(obj[i]));
1650 }
1651
1652 obj[i].body = dBodyCreate (world);
1653 for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
1654
1655 dMatrix3 R;
1656 if (random_pos) {
1657 dBodySetPosition (obj[i].body,
1658 (dRandReal()-0.5)*HFIELD_WIDTH*0.75,
1659 (dRandReal()-0.5)*HFIELD_DEPTH*0.75,
1660 dRandReal() + 2 );
1661 dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1662 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1663 }
1664 else {
1665 dReal maxheight = 0;
1666 for (k=0; k<num; k++) {
1667 const dReal *pos = dBodyGetPosition (obj[k].body);
1668 if (pos[2] > maxheight) maxheight = pos[2];
1669 }
1670 dBodySetPosition (obj[i].body, 0,maxheight+1,0);
1671 dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
1672 }
1673 dBodySetRotation (obj[i].body,R);
1674 dBodySetData (obj[i].body,(void*) i);
1675
1676 if (cmd == 'b')
1677 {
1678 dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
1679 obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
1680 }
1681 else if (cmd == 'c')
1682 {
1683 sides[0] *= 0.5;
1684 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
1685 obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
1686 }
1687 //<---- Convex Object
1688 else if (cmd == 'v')
1689 {
1690 dMassSetBox (&m,DENSITY,0.25,0.25,0.25);
1691 obj[i].geom[0] = dCreateConvex (space,
1692 planes,
1693 planecount,
1694 points,
1695 pointcount,
1696 polygons);
1697 }
1698 //----> Convex Object
1699 else if (cmd == 'y')
1700 {
1701 dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
1702 obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
1703 }
1704 else if (cmd == 's')
1705 {
1706 sides[0] *= 0.5;
1707 dMassSetSphere (&m,DENSITY,sides[0]);
1708 obj[i].geom[0] = dCreateSphere (space,sides[0]);
1709 }
1710#ifdef dTRIMESH_ENABLED
1711 else if (cmd == 'm')
1712 {
1713 dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
1714 dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
1715
1716 obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0);
1717
1718 // remember the mesh's dTriMeshDataID on its userdata for convenience.
1719 dGeomSetData(obj[i].geom[0], new_tmdata);
1720
1721 dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] );
1722 }
1723#endif
1724 else if (cmd == 'x')
1725 {
1726 dGeomID g2[GPB]; // encapsulated geometries
1727 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
1728
1729 // start accumulating masses for the encapsulated geometries
1730 dMass m2;
1731 dMassSetZero (&m);
1732
1733 // set random delta positions
1734 for (j=0; j<GPB; j++) {
1735 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
1736 }
1737
1738 for (k=0; k<GPB; k++) {
1739 obj[i].geom[k] = dCreateGeomTransform (space);
1740 dGeomTransformSetCleanup (obj[i].geom[k],1);
1741 if (k==0) {
1742 dReal radius = dRandReal()*0.25+0.05;
1743 g2[k] = dCreateSphere (0,radius);
1744 dMassSetSphere (&m2,DENSITY,radius);
1745 }
1746 else if (k==1) {
1747 g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
1748 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
1749 }
1750 else {
1751 dReal radius = dRandReal()*0.1+0.05;
1752 dReal length = dRandReal()*1.0+0.1;
1753 g2[k] = dCreateCapsule (0,radius,length);
1754 dMassSetCapsule (&m2,DENSITY,3,radius,length);
1755 }
1756 dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
1757
1758 // set the transformation (adjust the mass too)
1759 dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
1760 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
1761 dMatrix3 Rtx;
1762 dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1763 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1764 dGeomSetRotation (g2[k],Rtx);
1765 dMassRotate (&m2,Rtx);
1766
1767 // add to the total mass
1768 dMassAdd (&m,&m2);
1769 }
1770
1771 // move all encapsulated objects so that the center of mass is (0,0,0)
1772 for (k=0; k<2; k++) {
1773 dGeomSetPosition (g2[k],
1774 dpos[k][0]-m.c[0],
1775 dpos[k][1]-m.c[1],
1776 dpos[k][2]-m.c[2]);
1777 }
1778 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
1779 }
1780
1781 for (k=0; k < GPB; k++)
1782 {
1783 if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
1784 }
1785
1786 dBodySetMass (obj[i].body,&m);
1787 }
1788
1789
1790 //
1791 // Control Commands
1792 //
1793
1794 if (cmd == ' ') {
1795 selected++;
1796 if (selected >= num) selected = 0;
1797 if (selected < 0) selected = 0;
1798 }
1799 else if (cmd == 'd' && selected >= 0 && selected < num) {
1800 dBodyDisable (obj[selected].body);
1801 }
1802 else if (cmd == 'e' && selected >= 0 && selected < num) {
1803 dBodyEnable (obj[selected].body);
1804 }
1805 else if (cmd == 'a') {
1806 show_aabb ^= 1;
1807 }
1808 else if (cmd == 't') {
1809 show_contacts ^= 1;
1810 }
1811 else if (cmd == 'r') {
1812 random_pos ^= 1;
1813 }
1814 else if (cmd == '1') {
1815 write_world = 1;
1816 }
1817}
1818
1819
1820// draw a geom
1821
1822void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
1823{
1824 int i;
1825
1826 if (!g) return;
1827 if (!pos) pos = dGeomGetPosition (g);
1828 if (!R) R = dGeomGetRotation (g);
1829
1830 int type = dGeomGetClass (g);
1831 if (type == dBoxClass) {
1832 dVector3 sides;
1833 dGeomBoxGetLengths (g,sides);
1834 dsDrawBox (pos,R,sides);
1835 }
1836 else if (type == dSphereClass) {
1837 dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
1838 }
1839 else if (type == dCapsuleClass) {
1840 dReal radius,length;
1841 dGeomCapsuleGetParams (g,&radius,&length);
1842 dsDrawCapsule (pos,R,length,radius);
1843 }
1844 //<---- Convex Object
1845 else if (type == dConvexClass)
1846 {
1847 //dVector3 sides={0.50,0.50,0.50};
1848 dsDrawConvex(pos,R,planes,
1849 planecount,
1850 points,
1851 pointcount,
1852 polygons);
1853 }
1854 //----> Convex Object
1855 else if (type == dCylinderClass) {
1856 dReal radius,length;
1857 dGeomCylinderGetParams (g,&radius,&length);
1858 dsDrawCylinder (pos,R,length,radius);
1859 }
1860 else if (type == dGeomTransformClass) {
1861 dGeomID g2 = dGeomTransformGetGeom (g);
1862 const dReal *pos2 = dGeomGetPosition (g2);
1863 const dReal *R2 = dGeomGetRotation (g2);
1864 dVector3 actual_pos;
1865 dMatrix3 actual_R;
1866 dMULTIPLY0_331 (actual_pos,R,pos2);
1867 actual_pos[0] += pos[0];
1868 actual_pos[1] += pos[1];
1869 actual_pos[2] += pos[2];
1870 dMULTIPLY0_333 (actual_R,R,R2);
1871 drawGeom (g2,actual_pos,actual_R,0);
1872 }
1873
1874 if (show_aabb) {
1875 // draw the bounding box for this geom
1876 dReal aabb[6];
1877 dGeomGetAABB (g,aabb);
1878 dVector3 bbpos;
1879 for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
1880 dVector3 bbsides;
1881 for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
1882 dMatrix3 RI;
1883 dRSetIdentity (RI);
1884 dsSetColorAlpha (1,0,0,0.5);
1885 dsDrawBox (bbpos,RI,bbsides);
1886 }
1887
1888}
1889
1890// simulation loop
1891
1892static void simLoop (int pause)
1893{
1894 int i,j;
1895
1896 dsSetColor (0,0,2);
1897
1898 dSpaceCollide (space,0,&nearCallback);
1899
1900 //if (!pause) dWorldStep (world,0.05);
1901 //if (!pause) dWorldQuickStep (world,0.05);
1902 if (!pause) dWorldStepFast1 (world,0.05, 5);
1903
1904
1905 if (write_world) {
1906 FILE *f = fopen ("state.dif","wt");
1907 if (f) {
1908 dWorldExportDIF (world,f,"X");
1909 fclose (f);
1910 }
1911 write_world = 0;
1912 }
1913
1914 // remove all contact joints
1915 dJointGroupEmpty (contactgroup);
1916
1917
1918
1919 const dReal* pReal = dGeomGetPosition( gheight );
1920
1921 const dReal* RReal = dGeomGetRotation( gheight );
1922
1923 //
1924 // Draw Heightfield
1925 //
1926
1927 // Set ox and oz to zero for DHEIGHTFIELD_CORNER_ORIGIN mode.
1928 int ox = (int) ( -HFIELD_WIDTH/2 );
1929 int oz = (int) ( -HFIELD_DEPTH/2 );
1930
1931// for ( int tx = -1; tx < 2; ++tx )
1932// for ( int tz = -1; tz < 2; ++tz )
1933 {
1934 dsSetColorAlpha (0.5,1,0.5,0.5);
1935 dsSetTexture( DS_WOOD );
1936
1937 for ( int i = 0; i < HFIELD_WSTEP - 1; ++i )
1938 for ( int j = 0; j < HFIELD_DSTEP - 1; ++j )
1939 {
1940 dReal a[3], b[3], c[3], d[3];
1941
1942 a[ 0 ] = ox + ( i ) * HFIELD_WSAMP;
1943 a[ 1 ] = heightfield_callback( NULL, i, j );
1944 a[ 2 ] = oz + ( j ) * HFIELD_DSAMP;
1945
1946 b[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP;
1947 b[ 1 ] = heightfield_callback( NULL, i + 1, j );
1948 b[ 2 ] = oz + ( j ) * HFIELD_DSAMP;
1949
1950 c[ 0 ] = ox + ( i ) * HFIELD_WSAMP;
1951 c[ 1 ] = heightfield_callback( NULL, i, j + 1 );
1952 c[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP;
1953
1954 d[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP;
1955 d[ 1 ] = heightfield_callback( NULL, i + 1, j + 1 );
1956 d[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP;
1957
1958 dsDrawTriangle( pReal, RReal, a, c, b, 1 );
1959 dsDrawTriangle( pReal, RReal, b, c, d, 1 );
1960 }
1961 }
1962
1963
1964
1965
1966
1967 dsSetColor (1,1,0);
1968 dsSetTexture (DS_WOOD);
1969 for (i=0; i<num; i++)
1970 {
1971 for (j=0; j < GPB; j++)
1972 {
1973 if (i==selected)
1974 {
1975 dsSetColor (0,0.7,1);
1976 }
1977 else if (! dBodyIsEnabled (obj[i].body))
1978 {
1979 dsSetColor (1,0.8,0);
1980 }
1981 else
1982 {
1983 dsSetColor (1,1,0);
1984 }
1985
1986
1987 if ( obj[i].geom[j] && dGeomGetClass(obj[i].geom[j]) == dTriMeshClass )
1988 {
1989 int* Indices = (int*)::Indices;
1990
1991 // assume all trimeshes are drawn as bunnies
1992 const dReal* Pos = dGeomGetPosition(obj[i].geom[j]);
1993 const dReal* Rot = dGeomGetRotation(obj[i].geom[j]);
1994
1995 for (int ii = 0; ii < IndexCount / 3; ii++)
1996 {
1997 const dReal v[9] = { // explicit conversion from float to dReal
1998 Vertices[Indices[ii * 3 + 0] * 3 + 0],
1999 Vertices[Indices[ii * 3 + 0] * 3 + 1],
2000 Vertices[Indices[ii * 3 + 0] * 3 + 2],
2001 Vertices[Indices[ii * 3 + 1] * 3 + 0],
2002 Vertices[Indices[ii * 3 + 1] * 3 + 1],
2003 Vertices[Indices[ii * 3 + 1] * 3 + 2],
2004 Vertices[Indices[ii * 3 + 2] * 3 + 0],
2005 Vertices[Indices[ii * 3 + 2] * 3 + 1],
2006 Vertices[Indices[ii * 3 + 2] * 3 + 2]
2007 };
2008 dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
2009 }
2010
2011 // tell the tri-tri collider the current transform of the trimesh --
2012 // this is fairly important for good results.
2013
2014 // Fill in the (4x4) matrix.
2015 dReal* p_matrix = obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 );
2016
2017 p_matrix[ 0 ] = Rot[ 0 ]; p_matrix[ 1 ] = Rot[ 1 ]; p_matrix[ 2 ] = Rot[ 2 ]; p_matrix[ 3 ] = 0;
2018 p_matrix[ 4 ] = Rot[ 4 ]; p_matrix[ 5 ] = Rot[ 5 ]; p_matrix[ 6 ] = Rot[ 6 ]; p_matrix[ 7 ] = 0;
2019 p_matrix[ 8 ] = Rot[ 8 ]; p_matrix[ 9 ] = Rot[ 9 ]; p_matrix[10 ] = Rot[10 ]; p_matrix[11 ] = 0;
2020 p_matrix[12 ] = Pos[ 0 ]; p_matrix[13 ] = Pos[ 1 ]; p_matrix[14 ] = Pos[ 2 ]; p_matrix[15 ] = 1;
2021
2022 // Flip to other matrix.
2023 obj[i].last_matrix_index = !obj[i].last_matrix_index;
2024
2025 // Apply the 'other' matrix which is the oldest.
2026#ifdef dTRIMESH_ENABLED
2027 dGeomTriMeshSetLastTransform( obj[i].geom[j],
2028 *(dMatrix4*)( obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 ) ) );
2029#endif
2030 }
2031 else
2032 {
2033 drawGeom (obj[i].geom[j],0,0,show_aabb);
2034 }
2035 }
2036 }
2037
2038 if ( show_aabb )
2039 {
2040 // draw the bounding box for this geom
2041 dReal aabb[6];
2042 dGeomGetAABB (gheight,aabb);
2043 dVector3 bbpos;
2044 for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
2045 dVector3 bbsides;
2046 for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
2047 dMatrix3 RI;
2048 dRSetIdentity (RI);
2049 dsSetColorAlpha (1,0,0,0.5);
2050 dsDrawBox (bbpos,RI,bbsides);
2051 }
2052}
2053
2054
2055int main (int argc, char **argv)
2056{
2057 // setup pointers to drawstuff callback functions
2058 dsFunctions fn;
2059 fn.version = DS_VERSION;
2060 fn.start = &start;
2061 fn.step = &simLoop;
2062 fn.command = &command;
2063 fn.stop = 0;
2064 fn.path_to_textures = "../../drawstuff/textures";
2065 if(argc==2)
2066 {
2067 fn.path_to_textures = argv[1];
2068 }
2069
2070 // create world
2071 dInitODE();
2072 world = dWorldCreate();
2073 space = dHashSpaceCreate (0);
2074 contactgroup = dJointGroupCreate (0);
2075 dWorldSetGravity (world,0,0,-0.05);
2076 dWorldSetCFM (world,1e-5);
2077 dWorldSetAutoDisableFlag (world,1);
2078 dWorldSetContactMaxCorrectingVel (world,0.1);
2079 dWorldSetContactSurfaceLayer (world,0.001);
2080 memset (obj,0,sizeof(obj));
2081
2082#if 1
2083
2084 dWorldSetAutoDisableAverageSamplesCount( world, 1 );
2085
2086#endif
2087
2088 // base plane to catch overspill
2089 dCreatePlane( space, 0, 0, 1, 0 );
2090
2091
2092 // our heightfield floor
2093
2094 dHeightfieldDataID heightid = dGeomHeightfieldDataCreate();
2095
2096 // Create an finite heightfield.
2097 dGeomHeightfieldDataBuildCallback( heightid, NULL, heightfield_callback,
2098 HFIELD_WIDTH, HFIELD_DEPTH, HFIELD_WSTEP, HFIELD_DSTEP,
2099 REAL( 1.0 ), REAL( 0.0 ), REAL( 0.0 ), 0 );
2100
2101 // Give some very bounds which, while conservative,
2102 // makes AABB computation more accurate than +/-INF.
2103 dGeomHeightfieldDataSetBounds( heightid, REAL( -4.0 ), REAL( +6.0 ) );
2104
2105 gheight = dCreateHeightfield( space, heightid, 1 );
2106
2107 dVector3 pos;
2108 pos[ 0 ] = 0;
2109 pos[ 1 ] = 0;
2110 pos[ 2 ] = 0;
2111
2112 // Rotate so Z is up, not Y (which is the default orientation)
2113 dMatrix3 R;
2114 dRSetIdentity( R );
2115 dRFromAxisAndAngle( R, 1, 0, 0, DEGTORAD * 90 );
2116
2117 // Place it.
2118 dGeomSetRotation( gheight, R );
2119 dGeomSetPosition( gheight, pos[0], pos[1], pos[2] );
2120
2121
2122
2123
2124 // run simulation
2125 dsSimulationLoop (argc,argv,352,288,&fn);
2126
2127 dJointGroupDestroy (contactgroup);
2128 dSpaceDestroy (space);
2129 dWorldDestroy (world);
2130 dCloseODE();
2131 return 0;
2132}
diff --git a/libraries/ode-0.9/ode/demo/demo_hinge.cpp b/libraries/ode-0.9/ode/demo/demo_hinge.cpp
deleted file mode 100644
index 58e8f9e..0000000
--- a/libraries/ode-0.9/ode/demo/demo_hinge.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30// select correct drawing functions
31#ifdef dDOUBLE
32#define dsDrawBox dsDrawBoxD
33#endif
34
35
36// some constants
37#define SIDE (0.5f) // side length of a box
38#define MASS (1.0) // mass of a box
39
40
41// dynamics and collision objects
42static dWorldID world;
43static dBodyID body[2];
44static dJointID hinge;
45
46
47// state set by keyboard commands
48static int occasional_error = 0;
49
50
51// start simulation - set viewpoint
52
53static void start()
54{
55 static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
56 static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
57 dsSetViewpoint (xyz,hpr);
58 printf ("Press 'e' to start/stop occasional error.\n");
59}
60
61
62// called when a key pressed
63
64static void command (int cmd)
65{
66 if (cmd == 'e' || cmd == 'E') {
67 occasional_error ^= 1;
68 }
69}
70
71
72// simulation loop
73
74static void simLoop (int pause)
75{
76 const dReal kd = -0.3; // angular damping constant
77 if (!pause) {
78 // add an oscillating torque to body 0, and also damp its rotational motion
79 static dReal a=0;
80 const dReal *w = dBodyGetAngularVel (body[0]);
81 dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a));
82 dWorldStep (world,0.05);
83 a += 0.01;
84
85 // occasionally re-orient one of the bodies to create a deliberate error.
86 if (occasional_error) {
87 static int count = 0;
88 if ((count % 20)==0) {
89 // randomly adjust orientation of body[0]
90 const dReal *R1;
91 dMatrix3 R2,R3;
92 R1 = dBodyGetRotation (body[0]);
93 dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
94 dRandReal()-0.5,dRandReal()-0.5);
95 dMultiply0 (R3,R1,R2,3,3,3);
96 dBodySetRotation (body[0],R3);
97
98 // randomly adjust position of body[0]
99 const dReal *pos = dBodyGetPosition (body[0]);
100 dBodySetPosition (body[0],
101 pos[0]+0.2*(dRandReal()-0.5),
102 pos[1]+0.2*(dRandReal()-0.5),
103 pos[2]+0.2*(dRandReal()-0.5));
104 }
105 count++;
106 }
107 }
108
109 dReal sides1[3] = {SIDE,SIDE,SIDE};
110 dReal sides2[3] = {SIDE,SIDE,SIDE*0.8f};
111 dsSetTexture (DS_WOOD);
112 dsSetColor (1,1,0);
113 dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
114 dsSetColor (0,1,1);
115 dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
116}
117
118
119int main (int argc, char **argv)
120{
121 // setup pointers to drawstuff callback functions
122 dsFunctions fn;
123 fn.version = DS_VERSION;
124 fn.start = &start;
125 fn.step = &simLoop;
126 fn.command = &command;
127 fn.stop = 0;
128 fn.path_to_textures = "../../drawstuff/textures";
129 if(argc==2)
130 {
131 fn.path_to_textures = argv[1];
132 }
133
134 // create world
135 dInitODE();
136 world = dWorldCreate();
137
138 dMass m;
139 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
140 dMassAdjust (&m,MASS);
141
142 dQuaternion q;
143 dQFromAxisAndAngle (q,1,1,0,0.25*M_PI);
144
145 body[0] = dBodyCreate (world);
146 dBodySetMass (body[0],&m);
147 dBodySetPosition (body[0],0.5*SIDE,0.5*SIDE,1);
148 dBodySetQuaternion (body[0],q);
149
150 body[1] = dBodyCreate (world);
151 dBodySetMass (body[1],&m);
152 dBodySetPosition (body[1],-0.5*SIDE,-0.5*SIDE,1);
153 dBodySetQuaternion (body[1],q);
154
155 hinge = dJointCreateHinge (world,0);
156 dJointAttach (hinge,body[0],body[1]);
157 dJointSetHingeAnchor (hinge,0,0,1);
158 dJointSetHingeAxis (hinge,1,-1,1.41421356);
159
160 // run simulation
161 dsSimulationLoop (argc,argv,352,288,&fn);
162
163 dWorldDestroy (world);
164 dCloseODE();
165 return 0;
166}
diff --git a/libraries/ode-0.9/ode/demo/demo_jointPR.cpp b/libraries/ode-0.9/ode/demo/demo_jointPR.cpp
deleted file mode 100644
index e0d002d..0000000
--- a/libraries/ode-0.9/ode/demo/demo_jointPR.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25This file try to demonstrate how the PR joint is working.
26
27The axisP is draw in red and the axisR is in green
28
29*/
30
31
32#include <ode/ode.h>
33#include <drawstuff/drawstuff.h>
34#include <iostream>
35#include <math.h>
36
37
38#define DRAWSTUFF_TEXTURE_PATH "../../drawstuff/textures"
39
40
41#ifdef _MSC_VER
42#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
43#endif
44// select correct drawing functions
45#ifdef dDOUBLE
46#define dsDrawBox dsDrawBoxD
47#endif
48
49// physics parameters
50#define BOX1_LENGTH 2 // Size along the X axis
51#define BOX1_WIDTH 1 // Size along the Y axis
52#define BOX1_HEIGHT 0.4 // Size along the Z axis (up) since gravity is (0,0,-10)
53#define BOX2_LENGTH 0.2
54#define BOX2_WIDTH 0.1
55#define BOX2_HEIGHT 0.4
56#define Mass1 10
57#define Mass2 0.1
58
59
60#define PRISMATIC_ONLY 1
61#define ROTOIDE_ONLY 2
62int flag = 0;
63
64
65//camera view
66static float xyz[3] = {2.0f,-3.5f,2.0000f};
67static float hpr[3] = {90.000f,-25.5000f,0.0000f};
68//world,space,body & geom
69static dWorldID world;
70static dSpaceID space;
71static dSpaceID box1_space;
72static dSpaceID box2_space;
73static dBodyID box1_body[1];
74static dBodyID box2_body[1];
75static dJointID joint[1];
76static dJointGroupID contactgroup;
77static dGeomID ground;
78static dGeomID box1[1];
79static dGeomID box2[1];
80
81
82//collision detection
83static void nearCallback (void *data, dGeomID o1, dGeomID o2)
84{
85 int i,n;
86
87 dBodyID b1 = dGeomGetBody(o1);
88 dBodyID b2 = dGeomGetBody(o2);
89 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
90 const int N = 10;
91 dContact contact[N];
92 n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
93 if (n > 0)
94 {
95 for (i=0; i<n; i++)
96 {
97 contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
98 dContactSoftERP | dContactSoftCFM | dContactApprox1;
99 contact[i].surface.mu = 0.1;
100 contact[i].surface.slip1 = 0.02;
101 contact[i].surface.slip2 = 0.02;
102 contact[i].surface.soft_erp = 0.1;
103 contact[i].surface.soft_cfm = 0.0001;
104 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
105 dJointAttach (c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g2));
106 }
107 }
108}
109
110
111// start simulation - set viewpoint
112static void start()
113{
114 dsSetViewpoint (xyz,hpr);
115 printf ("Press 'd' to add force along positive x direction.\nPress 'a' to add force along negative x direction.\n");
116 printf ("Press 'w' to add force along positive y direction.\nPress 's' to add force along negative y direction.\n");
117 printf ("Press 'e' to add torque around positive z direction.\nPress 'q' to add torque around negative z direction.\n");
118 printf ("Press 'o' to add force around positive x direction \n");
119}
120
121// function to update camera position at each step.
122void update()
123{
124// const dReal *a =(dBodyGetPosition (box1_body[0]));
125// float dx=a[0];
126// float dy=a[1];
127// float dz=a[2];
128// xyz[0]=dx;
129// xyz[1]=dy-5;
130// xyz[2]=dz+2;
131// hpr[1]=-22.5000f;
132// dsSetViewpoint (xyz,hpr);
133}
134
135
136// called when a key pressed
137static void command (int cmd)
138{
139 switch(cmd)
140 {
141 case 'w': case 'W':
142 dBodyAddForce(box2_body[0],0,500,0);
143 std::cout<<(dBodyGetPosition(box2_body[0])[1]-dBodyGetPosition(box1_body[0])[1])<<'\n';
144 break;
145 case 's': case 'S':
146 dBodyAddForce(box2_body[0],0,-500,0);
147 std::cout<<(dBodyGetPosition(box2_body[0])[1]-dBodyGetPosition(box1_body[0])[1])<<'\n';
148 break;
149 case 'd': case 'D':
150 dBodyAddForce(box2_body[0],500,0,0);
151 std::cout<<(dBodyGetPosition(box2_body[0])[0]-dBodyGetPosition(box1_body[0])[0])<<'\n';
152 break;
153 case 'a': case 'A':
154 dBodyAddForce(box2_body[0],-500,0,0);
155 std::cout<<(dBodyGetPosition(box2_body[0])[0]-dBodyGetPosition(box1_body[0])[0])<<'\n';
156 break;
157 case 'e': case 'E':
158 dBodyAddRelTorque(box2_body[0],0,0,200);
159 break;
160 case 'q': case 'Q':
161 dBodyAddRelTorque(box2_body[0],0,0,-200);
162 break;
163 case 'o': case 'O':
164 dBodyAddForce(box1_body[0],10000,0,0);
165 break;
166 }
167}
168
169
170// simulation loop
171static void simLoop (int pause)
172{
173 if (!pause)
174 {
175 //draw 2 boxes
176 dVector3 ss;
177 dsSetTexture (DS_WOOD);
178
179 const dReal *posBox2 = dGeomGetPosition(box2[0]);
180 const dReal *rotBox2 = dGeomGetRotation(box2[0]);
181 dsSetColor (1,1,0);
182 dGeomBoxGetLengths (box2[0],ss);
183 dsDrawBox (posBox2, rotBox2, ss);
184
185 const dReal *posBox1 = dGeomGetPosition(box1[0]);
186 const dReal *rotBox1 = dGeomGetRotation(box1[0]);
187 dsSetColor (1,1,2);
188 dGeomBoxGetLengths (box1[0], ss);
189 dsDrawBox (posBox1, rotBox1, ss);
190
191 dVector3 anchorPos;
192 dJointGetPRAnchor (joint[0], anchorPos);
193
194 // Draw the axisP
195 if (ROTOIDE_ONLY != flag )
196 {
197 dsSetColor (1,0,0);
198 dVector3 sizeP = {0, 0.1, 0.1};
199 for (int i=0; i<3; ++i)
200 sizeP[0] += (anchorPos[i] - posBox1[i])*(anchorPos[i] - posBox1[i]);
201 sizeP[0] = sqrt(sizeP[0]);
202 dVector3 posAxisP;
203 for (int i=0; i<3; ++i)
204 posAxisP[i] = posBox1[i] + (anchorPos[i] - posBox1[i])/2.0;
205 dsDrawBox (posAxisP, rotBox1, sizeP);
206 }
207
208
209 // Draw the axisR
210 if (PRISMATIC_ONLY != flag )
211 {
212 dsSetColor (0,1,0);
213 dVector3 sizeR = {0, 0.1, 0.1};
214 for (int i=0; i<3; ++i)
215 sizeR[0] += (anchorPos[i] - posBox2[i])*(anchorPos[i] - posBox2[i]);
216 sizeR[0] = sqrt(sizeR[0]);
217 dVector3 posAxisR;
218 for (int i=0; i<3; ++i)
219 posAxisR[i] = posBox2[i] + (anchorPos[i] - posBox2[i])/2.0;
220 dsDrawBox (posAxisR, rotBox2, sizeR);
221 }
222
223 dSpaceCollide (space,0,&nearCallback);
224 dWorldQuickStep (world,0.0001);
225 update();
226 dJointGroupEmpty (contactgroup);
227 }
228}
229
230
231void Help(char **argv)
232{
233 printf("%s ", argv[0]);
234 printf(" -h | --help : print this help\n");
235 printf(" -b | --both : Display how the complete joint works\n");
236 printf(" Default behavior\n");
237 printf(" -p | --prismatic-only : Display how the prismatic part works\n");
238 printf(" The anchor pts is set at the center of body 2\n");
239 printf(" -r | --rotoide-only : Display how the rotoide part works\n");
240 printf(" The anchor pts is set at the center of body 1\n");
241 printf(" -t | --texture-path path : Path to the texture.\n");
242 printf(" Default = %s\n", DRAWSTUFF_TEXTURE_PATH);
243 printf("--------------------------------------------------\n");
244 printf("Hit any key to continue:");
245 getchar();
246
247 exit(0);
248}
249
250int main (int argc, char **argv)
251{
252 // setup pointers to drawstuff callback functions
253 dsFunctions fn;
254 fn.version = DS_VERSION;
255 fn.start = &start;
256 fn.step = &simLoop;
257 fn.command = &command;
258 fn.stop = 0;
259 fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
260
261 if (argc >= 2 )
262 {
263 for (int i=1; i < argc; ++i)
264 {
265 if( 0 == strcmp("-h", argv[i]) || 0 == strcmp("--help", argv[i]) )
266 Help(argv);
267
268 if(!flag && (0 == strcmp("-p", argv[i]) ||0 == strcmp("--prismatic-only", argv[i])) )
269 flag = PRISMATIC_ONLY;
270
271 if(!flag && (0 == strcmp("-r", argv[i]) || 0 == strcmp("--rotoide-only", argv[i])) )
272 flag = ROTOIDE_ONLY;
273
274 if(0 == strcmp("-t", argv[i]) || 0 == strcmp("--texture-path", argv[i]))
275 {
276 int j = i+1;
277 if ( j+1 > argc || // Check if we have enough arguments
278 argv[j] == '\0' || // We should have a path here
279 argv[j][0] == '-' ) // We should have a path not a command line
280 Help(argv);
281 else
282 fn.path_to_textures = argv[++i]; // Increase i since we use this argument
283 }
284 }
285 }
286
287 // create world
288 world = dWorldCreate();
289 space = dHashSpaceCreate (0);
290 contactgroup = dJointGroupCreate (0);
291 dWorldSetGravity (world,0,0,-10);
292 ground = dCreatePlane (space,0,0,1,0);
293
294 //create two boxes
295 dMass m;
296 box1_body[0] = dBodyCreate (world);
297 dMassSetBox (&m,1,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT);
298 dMassAdjust (&m,Mass1);
299 dBodySetMass (box1_body[0],&m);
300 box1[0] = dCreateBox (0,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT);
301 dGeomSetBody (box1[0],box1_body[0]);
302
303 box2_body[0] = dBodyCreate (world);
304 dMassSetBox (&m,10,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT);
305 dMassAdjust (&m,Mass2);
306 dBodySetMass (box2_body[0],&m);
307 box2[0] = dCreateBox (0,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT);
308 dGeomSetBody (box2[0],box2_body[0]);
309
310 //set the initial positions of body1 and body2
311 dMatrix3 R;
312 dRSetIdentity(R);
313 dBodySetPosition (box1_body[0],0,0,BOX1_HEIGHT/2.0);
314 dBodySetRotation (box1_body[0], R);
315
316 dBodySetPosition (box2_body[0],
317 2.1,
318 0.0,
319 BOX2_HEIGHT/2.0);
320 dBodySetRotation (box2_body[0], R);
321
322
323 //set PR joint
324 joint[0] = dJointCreatePR(world,0);
325 dJointAttach (joint[0],box1_body[0],box2_body[0]);
326 switch (flag)
327 {
328 case PRISMATIC_ONLY:
329 dJointSetPRAnchor (joint[0],
330 2.1,
331 0.0,
332 BOX2_HEIGHT/2.0);
333 dJointSetPRParam (joint[0],dParamLoStop, -0.5);
334 dJointSetPRParam (joint[0],dParamHiStop, 1.5);
335 break;
336
337 case ROTOIDE_ONLY:
338 dJointSetPRAnchor (joint[0],
339 0.0,
340 0.0,
341 BOX2_HEIGHT/2.0);
342 dJointSetPRParam (joint[0],dParamLoStop, 0.0);
343 dJointSetPRParam (joint[0],dParamHiStop, 0.0);
344 break;
345
346 default:
347 dJointSetPRAnchor (joint[0],
348 1.1,
349 0.0,
350 BOX2_HEIGHT/2.0);
351 dJointSetPRParam (joint[0],dParamLoStop, -0.5);
352 dJointSetPRParam (joint[0],dParamHiStop, 1.5);
353 break;
354 }
355
356 dJointSetPRAxis1(joint[0],1,0,0);
357 dJointSetPRAxis2(joint[0],0,0,1);
358// We position the 2 body
359// The position of the rotoide joint is on the second body so it can rotate on itself
360// and move along the X axis.
361// With this anchor
362// - A force in X will move only the body 2 inside the low and hi limit
363// of the prismatic
364// - A force in Y will make the 2 bodies to rotate around on the plane
365
366 box1_space = dSimpleSpaceCreate (space);
367 dSpaceSetCleanup (box1_space,0);
368 dSpaceAdd(box1_space,box1[0]);
369
370 // run simulation
371 dsSimulationLoop (argc,argv,400,300,&fn);
372 dJointGroupDestroy (contactgroup);
373 dSpaceDestroy (space);
374 dWorldDestroy (world);
375 return 0;
376}
377
diff --git a/libraries/ode-0.9/ode/demo/demo_joints.cpp b/libraries/ode-0.9/ode/demo/demo_joints.cpp
deleted file mode 100644
index 2a83c2f..0000000
--- a/libraries/ode-0.9/ode/demo/demo_joints.cpp
+++ /dev/null
@@ -1,1092 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25perform tests on all the joint types.
26this should be done using the double precision version of the library.
27
28usage:
29 test_joints [-nXXX] [-g] [-i] [-e] [path_to_textures]
30
31if a test number is given then that specific test is performed, otherwise
32all the tests are performed. the tests are numbered `xxyy', where xx
33corresponds to the joint type and yy is the sub-test number. not every
34number maps to an actual test.
35
36flags:
37 i: the test is interactive.
38 g: turn off graphical display (can't use this with `i').
39 e: turn on occasional error perturbations
40 n: performe test XXX
41some tests compute and display error values. these values are scaled so
42<1 is good and >1 is bad. other tests just show graphical results which
43you must verify visually.
44
45*/
46
47#include <ctype.h>
48#include <ode/ode.h>
49#include <drawstuff/drawstuff.h>
50
51#ifdef _MSC_VER
52#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
53#endif
54
55// select correct drawing functions
56#ifdef dDOUBLE
57#define dsDrawBox dsDrawBoxD
58#endif
59
60
61// some constants
62#define NUM_JOINTS 10 // number of joints to test (the `xx' value)
63#define SIDE (0.5f) // side length of a box - don't change this
64#define MASS (1.0) // mass of a box
65#define STEPSIZE 0.05
66
67
68// dynamics objects
69static dWorldID world;
70static dBodyID body[2];
71static dJointID joint;
72
73
74// data from the command line arguments
75static int cmd_test_num = -1;
76static int cmd_interactive = 0;
77static int cmd_graphics = 1;
78static char *cmd_path_to_textures = NULL;
79static int cmd_occasional_error = 0; // perturb occasionally
80
81
82// info about the current test
83struct TestInfo;
84static int test_num = 0; // number of the current test
85static int iteration = 0;
86static int max_iterations = 0;
87static dReal max_error = 0;
88
89//****************************************************************************
90// utility stuff
91
92static char loCase (char a)
93{
94 if (a >= 'A' && a <= 'Z') return a + ('a'-'A');
95 else return a;
96}
97
98
99static dReal length (dVector3 a)
100{
101 return dSqrt (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
102}
103
104
105// get the max difference between a 3x3 matrix and the identity
106
107dReal cmpIdentity (const dMatrix3 A)
108{
109 dMatrix3 I;
110 dSetZero (I,12);
111 I[0] = 1;
112 I[5] = 1;
113 I[10] = 1;
114 return dMaxDifference (A,I,3,3);
115}
116
117//****************************************************************************
118// test world construction and utilities
119
120void constructWorldForTest (dReal gravity, int bodycount,
121 /* body 1 pos */ dReal pos1x, dReal pos1y, dReal pos1z,
122 /* body 2 pos */ dReal pos2x, dReal pos2y, dReal pos2z,
123 /* body 1 rotation axis */ dReal ax1x, dReal ax1y, dReal ax1z,
124 /* body 1 rotation axis */ dReal ax2x, dReal ax2y, dReal ax2z,
125 /* rotation angles */ dReal a1, dReal a2)
126{
127 // create world
128 world = dWorldCreate();
129 dWorldSetERP (world,0.2);
130 dWorldSetCFM (world,1e-6);
131 dWorldSetGravity (world,0,0,gravity);
132
133 dMass m;
134 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
135 dMassAdjust (&m,MASS);
136
137 body[0] = dBodyCreate (world);
138 dBodySetMass (body[0],&m);
139 dBodySetPosition (body[0], pos1x, pos1y, pos1z);
140 dQuaternion q;
141 dQFromAxisAndAngle (q,ax1x,ax1y,ax1z,a1);
142 dBodySetQuaternion (body[0],q);
143
144 if (bodycount==2) {
145 body[1] = dBodyCreate (world);
146 dBodySetMass (body[1],&m);
147 dBodySetPosition (body[1], pos2x, pos2y, pos2z);
148 dQFromAxisAndAngle (q,ax2x,ax2y,ax2z,a2);
149 dBodySetQuaternion (body[1],q);
150 }
151 else body[1] = 0;
152}
153
154
155// add an oscillating torque to body 0
156
157void addOscillatingTorque (dReal tscale)
158{
159 static dReal a=0;
160 dBodyAddTorque (body[0],tscale*cos(2*a),tscale*cos(2.7183*a),
161 tscale*cos(1.5708*a));
162 a += 0.01;
163}
164
165
166void addOscillatingTorqueAbout(dReal tscale, dReal x, dReal y, dReal z)
167{
168 static dReal a=0;
169 dBodyAddTorque (body[0], tscale*cos(a) * x, tscale*cos(a) * y,
170 tscale * cos(a) * z);
171 a += 0.02;
172}
173
174
175// damp the rotational motion of body 0 a bit
176
177void dampRotationalMotion (dReal kd)
178{
179 const dReal *w = dBodyGetAngularVel (body[0]);
180 dBodyAddTorque (body[0],-kd*w[0],-kd*w[1],-kd*w[2]);
181}
182
183
184// add a spring force to keep the bodies together, otherwise they may fly
185// apart with some joints.
186
187void addSpringForce (dReal ks)
188{
189 const dReal *p1 = dBodyGetPosition (body[0]);
190 const dReal *p2 = dBodyGetPosition (body[1]);
191 dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]),ks*(p2[2]-p1[2]));
192 dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]),ks*(p1[2]-p2[2]));
193}
194
195
196// add an oscillating Force to body 0
197
198void addOscillatingForce (dReal fscale)
199{
200 static dReal a=0;
201 dBodyAddForce (body[0],fscale*cos(2*a),fscale*cos(2.7183*a),
202 fscale*cos(1.5708*a));
203 a += 0.01;
204}
205
206//****************************************************************************
207// stuff specific to the tests
208//
209// 0xx : fixed
210// 1xx : ball and socket
211// 2xx : hinge
212// 3xx : slider
213// 4xx : hinge 2
214// 5xx : contact
215// 6xx : amotor
216// 7xx : universal joint
217// 8xx : PR joint (Prismatic and Rotoide)
218
219// setup for the given test. return 0 if there is no such test
220
221int setupTest (int n)
222{
223 switch (n) {
224
225 // ********** fixed joint
226
227 case 0: { // 2 body
228 constructWorldForTest (0,2,
229 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
230 1,1,0, 1,1,0,
231 0.25*M_PI,0.25*M_PI);
232 joint = dJointCreateFixed (world,0);
233 dJointAttach (joint,body[0],body[1]);
234 dJointSetFixed (joint);
235 return 1;
236 }
237
238 case 1: { // 1 body to static env
239 constructWorldForTest (0,1,
240 0.5*SIDE,0.5*SIDE,1, 0,0,0,
241 1,0,0, 1,0,0,
242 0,0);
243 joint = dJointCreateFixed (world,0);
244 dJointAttach (joint,body[0],0);
245 dJointSetFixed (joint);
246 return 1;
247 }
248
249 case 2: { // 2 body with relative rotation
250 constructWorldForTest (0,2,
251 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
252 1,1,0, 1,1,0,
253 0.25*M_PI,-0.25*M_PI);
254 joint = dJointCreateFixed (world,0);
255 dJointAttach (joint,body[0],body[1]);
256 dJointSetFixed (joint);
257 return 1;
258 }
259
260 case 3: { // 1 body to static env with relative rotation
261 constructWorldForTest (0,1,
262 0.5*SIDE,0.5*SIDE,1, 0,0,0,
263 1,0,0, 1,0,0,
264 0.25*M_PI,0);
265 joint = dJointCreateFixed (world,0);
266 dJointAttach (joint,body[0],0);
267 dJointSetFixed (joint);
268 return 1;
269 }
270
271 // ********** hinge joint
272
273 case 200: // 2 body
274 constructWorldForTest (0,2,
275 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
276 1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI);
277 joint = dJointCreateHinge (world,0);
278 dJointAttach (joint,body[0],body[1]);
279 dJointSetHingeAnchor (joint,0,0,1);
280 dJointSetHingeAxis (joint,1,-1,1.41421356);
281 return 1;
282
283 case 220: // hinge angle polarity test
284 case 221: // hinge angle rate test
285 constructWorldForTest (0,2,
286 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
287 1,0,0, 1,0,0, 0,0);
288 joint = dJointCreateHinge (world,0);
289 dJointAttach (joint,body[0],body[1]);
290 dJointSetHingeAnchor (joint,0,0,1);
291 dJointSetHingeAxis (joint,0,0,1);
292 max_iterations = 50;
293 return 1;
294
295 case 230: // hinge motor rate (and polarity) test
296 case 231: // ...with stops
297 constructWorldForTest (0,2,
298 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
299 1,0,0, 1,0,0, 0,0);
300 joint = dJointCreateHinge (world,0);
301 dJointAttach (joint,body[0],body[1]);
302 dJointSetHingeAnchor (joint,0,0,1);
303 dJointSetHingeAxis (joint,0,0,1);
304 dJointSetHingeParam (joint,dParamFMax,1);
305 if (n==231) {
306 dJointSetHingeParam (joint,dParamLoStop,-0.5);
307 dJointSetHingeParam (joint,dParamHiStop,0.5);
308 }
309 return 1;
310
311 case 250: // limit bounce test (gravity down)
312 case 251: { // ...gravity up
313 constructWorldForTest ((n==251) ? 0.1 : -0.1, 2,
314 0.5*SIDE,0,1+0.5*SIDE, -0.5*SIDE,0,1-0.5*SIDE,
315 1,0,0, 1,0,0, 0,0);
316 joint = dJointCreateHinge (world,0);
317 dJointAttach (joint,body[0],body[1]);
318 dJointSetHingeAnchor (joint,0,0,1);
319 dJointSetHingeAxis (joint,0,1,0);
320 dJointSetHingeParam (joint,dParamLoStop,-0.9);
321 dJointSetHingeParam (joint,dParamHiStop,0.7854);
322 dJointSetHingeParam (joint,dParamBounce,0.5);
323 // anchor 2nd body with a fixed joint
324 dJointID j = dJointCreateFixed (world,0);
325 dJointAttach (j,body[1],0);
326 dJointSetFixed (j);
327 return 1;
328 }
329
330 // ********** slider
331
332 case 300: // 2 body
333 constructWorldForTest (0,2,
334 0,0,1, 0.2,0.2,1.2,
335 0,0,1, -1,1,0, 0,0.25*M_PI);
336 joint = dJointCreateSlider (world,0);
337 dJointAttach (joint,body[0],body[1]);
338 dJointSetSliderAxis (joint,1,1,1);
339 return 1;
340
341 case 320: // slider angle polarity test
342 case 321: // slider angle rate test
343 constructWorldForTest (0,2,
344 0,0,1, 0,0,1.2,
345 1,0,0, 1,0,0, 0,0);
346 joint = dJointCreateSlider (world,0);
347 dJointAttach (joint,body[0],body[1]);
348 dJointSetSliderAxis (joint,0,0,1);
349 max_iterations = 50;
350 return 1;
351
352 case 330: // slider motor rate (and polarity) test
353 case 331: // ...with stops
354 constructWorldForTest (0, 2,
355 0,0,1, 0,0,1.2,
356 1,0,0, 1,0,0, 0,0);
357 joint = dJointCreateSlider (world,0);
358 dJointAttach (joint,body[0],body[1]);
359 dJointSetSliderAxis (joint,0,0,1);
360 dJointSetSliderParam (joint,dParamFMax,100);
361 if (n==331) {
362 dJointSetSliderParam (joint,dParamLoStop,-0.4);
363 dJointSetSliderParam (joint,dParamHiStop,0.4);
364 }
365 return 1;
366
367 case 350: // limit bounce tests
368 case 351: {
369 constructWorldForTest ((n==351) ? 0.1 : -0.1, 2,
370 0,0,1, 0,0,1.2,
371 1,0,0, 1,0,0, 0,0);
372 joint = dJointCreateSlider (world,0);
373 dJointAttach (joint,body[0],body[1]);
374 dJointSetSliderAxis (joint,0,0,1);
375 dJointSetSliderParam (joint,dParamLoStop,-0.5);
376 dJointSetSliderParam (joint,dParamHiStop,0.5);
377 dJointSetSliderParam (joint,dParamBounce,0.5);
378 // anchor 2nd body with a fixed joint
379 dJointID j = dJointCreateFixed (world,0);
380 dJointAttach (j,body[1],0);
381 dJointSetFixed (j);
382 return 1;
383 }
384
385 // ********** hinge-2 joint
386
387 case 420: // hinge-2 steering angle polarity test
388 case 421: // hinge-2 steering angle rate test
389 constructWorldForTest (0,2,
390 0.5*SIDE,0,1, -0.5*SIDE,0,1,
391 1,0,0, 1,0,0, 0,0);
392 joint = dJointCreateHinge2 (world,0);
393 dJointAttach (joint,body[0],body[1]);
394 dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1);
395 dJointSetHinge2Axis1 (joint,0,0,1);
396 dJointSetHinge2Axis2 (joint,1,0,0);
397 max_iterations = 50;
398 return 1;
399
400 case 430: // hinge 2 steering motor rate (+polarity) test
401 case 431: // ...with stops
402 case 432: // hinge 2 wheel motor rate (+polarity) test
403 constructWorldForTest (0,2,
404 0.5*SIDE,0,1, -0.5*SIDE,0,1,
405 1,0,0, 1,0,0, 0,0);
406 joint = dJointCreateHinge2 (world,0);
407 dJointAttach (joint,body[0],body[1]);
408 dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1);
409 dJointSetHinge2Axis1 (joint,0,0,1);
410 dJointSetHinge2Axis2 (joint,1,0,0);
411 dJointSetHinge2Param (joint,dParamFMax,1);
412 dJointSetHinge2Param (joint,dParamFMax2,1);
413 if (n==431) {
414 dJointSetHinge2Param (joint,dParamLoStop,-0.5);
415 dJointSetHinge2Param (joint,dParamHiStop,0.5);
416 }
417 return 1;
418
419 // ********** angular motor joint
420
421 case 600: // test euler angle calculations
422 constructWorldForTest (0,2,
423 -SIDE*0.5,0,1, SIDE*0.5,0,1,
424 0,0,1, 0,0,1, 0,0);
425 joint = dJointCreateAMotor (world,0);
426 dJointAttach (joint,body[0],body[1]);
427
428 dJointSetAMotorNumAxes (joint,3);
429 dJointSetAMotorAxis (joint,0,1, 0,0,1);
430 dJointSetAMotorAxis (joint,2,2, 1,0,0);
431 dJointSetAMotorMode (joint,dAMotorEuler);
432 max_iterations = 200;
433 return 1;
434
435 // ********** universal joint
436
437 case 700: // 2 body
438 case 701:
439 case 702:
440 constructWorldForTest (0,2,
441 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
442 1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI);
443 joint = dJointCreateUniversal (world,0);
444 dJointAttach (joint,body[0],body[1]);
445 dJointSetUniversalAnchor (joint,0,0,1);
446 dJointSetUniversalAxis1 (joint, 1, -1, 1.41421356);
447 dJointSetUniversalAxis2 (joint, 1, -1, -1.41421356);
448 return 1;
449
450 case 720: // universal transmit torque test
451 case 721:
452 case 722:
453 case 730: // universal torque about axis 1
454 case 731:
455 case 732:
456 case 740: // universal torque about axis 2
457 case 741:
458 case 742:
459 constructWorldForTest (0,2,
460 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
461 1,0,0, 1,0,0, 0,0);
462 joint = dJointCreateUniversal (world,0);
463 dJointAttach (joint,body[0],body[1]);
464 dJointSetUniversalAnchor (joint,0,0,1);
465 dJointSetUniversalAxis1 (joint,0,0,1);
466 dJointSetUniversalAxis2 (joint, 1, -1,0);
467 max_iterations = 100;
468 return 1;
469
470 // Joint PR (Prismatic and Rotoide)
471 case 800: // 2 body
472 case 801: // 2 bodies with spring force and prismatic fixed
473 case 802: // 2 bodies with torque on body1 and prismatic fixed
474 constructWorldForTest (0, 2,
475 -1.0, 0.0, 1.0,
476 1.0, 0.0, 1.0,
477 1,0,0, 1,0,0,
478 0, 0);
479 joint = dJointCreatePR (world, 0);
480 dJointAttach (joint, body[0], body[1]);
481 dJointSetPRAnchor (joint,-0.5, 0.0, 1.0);
482 dJointSetPRAxis1 (joint, 0, 1, 0);
483 dJointSetPRAxis2 (joint, 1, 0, 0);
484 dJointSetPRParam (joint,dParamLoStop,-0.5);
485 dJointSetPRParam (joint,dParamHiStop,0.5);
486 dJointSetPRParam (joint,dParamLoStop2,0);
487 dJointSetPRParam (joint,dParamHiStop2,0);
488 return 1;
489 case 803: // 2 bodies with spring force and prismatic NOT fixed
490 case 804: // 2 bodies with torque force and prismatic NOT fixed
491 case 805: // 2 bodies with force only on first body
492 constructWorldForTest (0, 2,
493 -1.0, 0.0, 1.0,
494 1.0, 0.0, 1.0,
495 1,0,0, 1,0,0,
496 0, 0);
497 joint = dJointCreatePR (world, 0);
498 dJointAttach (joint, body[0], body[1]);
499 dJointSetPRAnchor (joint,-0.5, 0.0, 1.0);
500 dJointSetPRAxis1 (joint, 0, 1, 0);
501 dJointSetPRAxis2 (joint, 1, 0, 0);
502 dJointSetPRParam (joint,dParamLoStop,-0.5);
503 dJointSetPRParam (joint,dParamHiStop,0.5);
504 dJointSetPRParam (joint,dParamLoStop2,-0.5);
505 dJointSetPRParam (joint,dParamHiStop2,0.5);
506 return 1;
507 }
508 return 0;
509}
510
511
512// do stuff specific to this test each iteration. you can check some
513// invariants for the test -- the return value is some scaled error measurement
514// that must be less than 1.
515// return a dInfinity if error is not measured for this n.
516
517dReal doStuffAndGetError (int n)
518{
519 switch (n) {
520
521 // ********** fixed joint
522
523 case 0: { // 2 body
524 addOscillatingTorque (0.1);
525 dampRotationalMotion (0.1);
526 // check the orientations are the same
527 const dReal *R1 = dBodyGetRotation (body[0]);
528 const dReal *R2 = dBodyGetRotation (body[1]);
529 dReal err1 = dMaxDifference (R1,R2,3,3);
530 // check the body offset is correct
531 dVector3 p,pp;
532 const dReal *p1 = dBodyGetPosition (body[0]);
533 const dReal *p2 = dBodyGetPosition (body[1]);
534 for (int i=0; i<3; i++) p[i] = p2[i] - p1[i];
535 dMULTIPLY1_331 (pp,R1,p);
536 pp[0] += 0.5;
537 pp[1] += 0.5;
538 return (err1 + length (pp)) * 300;
539 }
540
541 case 1: { // 1 body to static env
542 addOscillatingTorque (0.1);
543
544 // check the orientation is the identity
545 dReal err1 = cmpIdentity (dBodyGetRotation (body[0]));
546
547 // check the body offset is correct
548 dVector3 p;
549 const dReal *p1 = dBodyGetPosition (body[0]);
550 for (int i=0; i<3; i++) p[i] = p1[i];
551 p[0] -= 0.25;
552 p[1] -= 0.25;
553 p[2] -= 1;
554 return (err1 + length (p)) * 1e6;
555 }
556
557 case 2: { // 2 body
558 addOscillatingTorque (0.1);
559 dampRotationalMotion (0.1);
560 // check the body offset is correct
561 // Should really check body rotation too. Oh well.
562 const dReal *R1 = dBodyGetRotation (body[0]);
563 dVector3 p,pp;
564 const dReal *p1 = dBodyGetPosition (body[0]);
565 const dReal *p2 = dBodyGetPosition (body[1]);
566 for (int i=0; i<3; i++) p[i] = p2[i] - p1[i];
567 dMULTIPLY1_331 (pp,R1,p);
568 pp[0] += 0.5;
569 pp[1] += 0.5;
570 return length(pp) * 300;
571 }
572
573 case 3: { // 1 body to static env with relative rotation
574 addOscillatingTorque (0.1);
575
576 // check the body offset is correct
577 dVector3 p;
578 const dReal *p1 = dBodyGetPosition (body[0]);
579 for (int i=0; i<3; i++) p[i] = p1[i];
580 p[0] -= 0.25;
581 p[1] -= 0.25;
582 p[2] -= 1;
583 return length (p) * 1e6;
584 }
585
586
587 // ********** hinge joint
588
589 case 200: // 2 body
590 addOscillatingTorque (0.1);
591 dampRotationalMotion (0.1);
592 return dInfinity;
593
594 case 220: // hinge angle polarity test
595 dBodyAddTorque (body[0],0,0,0.01);
596 dBodyAddTorque (body[1],0,0,-0.01);
597 if (iteration == 40) {
598 dReal a = dJointGetHingeAngle (joint);
599 if (a > 0.5 && a < 1) return 0; else return 10;
600 }
601 return 0;
602
603 case 221: { // hinge angle rate test
604 static dReal last_angle = 0;
605 dBodyAddTorque (body[0],0,0,0.01);
606 dBodyAddTorque (body[1],0,0,-0.01);
607 dReal a = dJointGetHingeAngle (joint);
608 dReal r = dJointGetHingeAngleRate (joint);
609 dReal er = (a-last_angle)/STEPSIZE; // estimated rate
610 last_angle = a;
611 return fabs(r-er) * 4e4;
612 }
613
614 case 230: // hinge motor rate (and polarity) test
615 case 231: { // ...with stops
616 static dReal a = 0;
617 dReal r = dJointGetHingeAngleRate (joint);
618 dReal err = fabs (cos(a) - r);
619 if (a==0) err = 0;
620 a += 0.03;
621 dJointSetHingeParam (joint,dParamVel,cos(a));
622 if (n==231) return dInfinity;
623 return err * 1e6;
624 }
625
626 // ********** slider joint
627
628 case 300: // 2 body
629 addOscillatingTorque (0.05);
630 dampRotationalMotion (0.1);
631 addSpringForce (0.5);
632 return dInfinity;
633
634 case 320: // slider angle polarity test
635 dBodyAddForce (body[0],0,0,0.1);
636 dBodyAddForce (body[1],0,0,-0.1);
637 if (iteration == 40) {
638 dReal a = dJointGetSliderPosition (joint);
639 if (a > 0.2 && a < 0.5) return 0; else return 10;
640 return a;
641 }
642 return 0;
643
644 case 321: { // slider angle rate test
645 static dReal last_pos = 0;
646 dBodyAddForce (body[0],0,0,0.1);
647 dBodyAddForce (body[1],0,0,-0.1);
648 dReal p = dJointGetSliderPosition (joint);
649 dReal r = dJointGetSliderPositionRate (joint);
650 dReal er = (p-last_pos)/STEPSIZE; // estimated rate (almost exact)
651 last_pos = p;
652 return fabs(r-er) * 1e9;
653 }
654
655 case 330: // slider motor rate (and polarity) test
656 case 331: { // ...with stops
657 static dReal a = 0;
658 dReal r = dJointGetSliderPositionRate (joint);
659 dReal err = fabs (0.7*cos(a) - r);
660 if (a < 0.04) err = 0;
661 a += 0.03;
662 dJointSetSliderParam (joint,dParamVel,0.7*cos(a));
663 if (n==331) return dInfinity;
664 return err * 1e6;
665 }
666
667 // ********** hinge-2 joint
668
669 case 420: // hinge-2 steering angle polarity test
670 dBodyAddTorque (body[0],0,0,0.01);
671 dBodyAddTorque (body[1],0,0,-0.01);
672 if (iteration == 40) {
673 dReal a = dJointGetHinge2Angle1 (joint);
674 if (a > 0.5 && a < 0.6) return 0; else return 10;
675 }
676 return 0;
677
678 case 421: { // hinge-2 steering angle rate test
679 static dReal last_angle = 0;
680 dBodyAddTorque (body[0],0,0,0.01);
681 dBodyAddTorque (body[1],0,0,-0.01);
682 dReal a = dJointGetHinge2Angle1 (joint);
683 dReal r = dJointGetHinge2Angle1Rate (joint);
684 dReal er = (a-last_angle)/STEPSIZE; // estimated rate
685 last_angle = a;
686 return fabs(r-er)*2e4;
687 }
688
689 case 430: // hinge 2 steering motor rate (+polarity) test
690 case 431: { // ...with stops
691 static dReal a = 0;
692 dReal r = dJointGetHinge2Angle1Rate (joint);
693 dReal err = fabs (cos(a) - r);
694 if (a==0) err = 0;
695 a += 0.03;
696 dJointSetHinge2Param (joint,dParamVel,cos(a));
697 if (n==431) return dInfinity;
698 return err * 1e6;
699 }
700
701 case 432: { // hinge 2 wheel motor rate (+polarity) test
702 static dReal a = 0;
703 dReal r = dJointGetHinge2Angle2Rate (joint);
704 dReal err = fabs (cos(a) - r);
705 if (a==0) err = 0;
706 a += 0.03;
707 dJointSetHinge2Param (joint,dParamVel2,cos(a));
708 return err * 1e6;
709 }
710
711 // ********** angular motor joint
712
713 case 600: { // test euler angle calculations
714 // desired euler angles from last iteration
715 static dReal a1,a2,a3;
716
717 // find actual euler angles
718 dReal aa1 = dJointGetAMotorAngle (joint,0);
719 dReal aa2 = dJointGetAMotorAngle (joint,1);
720 dReal aa3 = dJointGetAMotorAngle (joint,2);
721 // printf ("actual = %.4f %.4f %.4f\n\n",aa1,aa2,aa3);
722
723 dReal err = dInfinity;
724 if (iteration > 0) {
725 err = dFabs(aa1-a1) + dFabs(aa2-a2) + dFabs(aa3-a3);
726 err *= 1e10;
727 }
728
729 // get random base rotation for both bodies
730 dMatrix3 Rbase;
731 dRFromAxisAndAngle (Rbase, 3*(dRandReal()-0.5), 3*(dRandReal()-0.5),
732 3*(dRandReal()-0.5), 3*(dRandReal()-0.5));
733 dBodySetRotation (body[0],Rbase);
734
735 // rotate body 2 by random euler angles w.r.t. body 1
736 a1 = 3.14 * 2 * (dRandReal()-0.5);
737 a2 = 1.57 * 2 * (dRandReal()-0.5);
738 a3 = 3.14 * 2 * (dRandReal()-0.5);
739 dMatrix3 R1,R2,R3,Rtmp1,Rtmp2;
740 dRFromAxisAndAngle (R1,0,0,1,-a1);
741 dRFromAxisAndAngle (R2,0,1,0,a2);
742 dRFromAxisAndAngle (R3,1,0,0,-a3);
743 dMultiply0 (Rtmp1,R2,R3,3,3,3);
744 dMultiply0 (Rtmp2,R1,Rtmp1,3,3,3);
745 dMultiply0 (Rtmp1,Rbase,Rtmp2,3,3,3);
746 dBodySetRotation (body[1],Rtmp1);
747 // printf ("desired = %.4f %.4f %.4f\n",a1,a2,a3);
748
749 return err;
750 }
751
752 // ********** universal joint
753
754 case 700: { // 2 body: joint constraint
755 dVector3 ax1, ax2;
756
757 addOscillatingTorque (0.1);
758 dampRotationalMotion (0.1);
759 dJointGetUniversalAxis1(joint, ax1);
760 dJointGetUniversalAxis2(joint, ax2);
761 return fabs(10*dDOT(ax1, ax2));
762 }
763
764 case 701: { // 2 body: angle 1 rate
765 static dReal last_angle = 0;
766 addOscillatingTorque (0.1);
767 dampRotationalMotion (0.1);
768 dReal a = dJointGetUniversalAngle1(joint);
769 dReal r = dJointGetUniversalAngle1Rate(joint);
770 dReal diff = a - last_angle;
771 if (diff > M_PI) diff -= 2*M_PI;
772 if (diff < -M_PI) diff += 2*M_PI;
773 dReal er = diff / STEPSIZE; // estimated rate
774 last_angle = a;
775 // I'm not sure why the error is so large here.
776 return fabs(r - er) * 1e1;
777 }
778
779 case 702: { // 2 body: angle 2 rate
780 static dReal last_angle = 0;
781 addOscillatingTorque (0.1);
782 dampRotationalMotion (0.1);
783 dReal a = dJointGetUniversalAngle2(joint);
784 dReal r = dJointGetUniversalAngle2Rate(joint);
785 dReal diff = a - last_angle;
786 if (diff > M_PI) diff -= 2*M_PI;
787 if (diff < -M_PI) diff += 2*M_PI;
788 dReal er = diff / STEPSIZE; // estimated rate
789 last_angle = a;
790 // I'm not sure why the error is so large here.
791 return fabs(r - er) * 1e1;
792 }
793
794 case 720: { // universal transmit torque test: constraint error
795 dVector3 ax1, ax2;
796 addOscillatingTorqueAbout (0.1, 1, 1, 0);
797 dampRotationalMotion (0.1);
798 dJointGetUniversalAxis1(joint, ax1);
799 dJointGetUniversalAxis2(joint, ax2);
800 return fabs(10*dDOT(ax1, ax2));
801 }
802
803 case 721: { // universal transmit torque test: angle1 rate
804 static dReal last_angle = 0;
805 addOscillatingTorqueAbout (0.1, 1, 1, 0);
806 dampRotationalMotion (0.1);
807 dReal a = dJointGetUniversalAngle1(joint);
808 dReal r = dJointGetUniversalAngle1Rate(joint);
809 dReal diff = a - last_angle;
810 if (diff > M_PI) diff -= 2*M_PI;
811 if (diff < -M_PI) diff += 2*M_PI;
812 dReal er = diff / STEPSIZE; // estimated rate
813 last_angle = a;
814 return fabs(r - er) * 1e10;
815 }
816
817 case 722: { // universal transmit torque test: angle2 rate
818 static dReal last_angle = 0;
819 addOscillatingTorqueAbout (0.1, 1, 1, 0);
820 dampRotationalMotion (0.1);
821 dReal a = dJointGetUniversalAngle2(joint);
822 dReal r = dJointGetUniversalAngle2Rate(joint);
823 dReal diff = a - last_angle;
824 if (diff > M_PI) diff -= 2*M_PI;
825 if (diff < -M_PI) diff += 2*M_PI;
826 dReal er = diff / STEPSIZE; // estimated rate
827 last_angle = a;
828 return fabs(r - er) * 1e10;
829 }
830
831 case 730:{
832 dVector3 ax1, ax2;
833 dJointGetUniversalAxis1(joint, ax1);
834 dJointGetUniversalAxis2(joint, ax2);
835 addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
836 dampRotationalMotion (0.1);
837 return fabs(10*dDOT(ax1, ax2));
838 }
839
840 case 731:{
841 dVector3 ax1;
842 static dReal last_angle = 0;
843 dJointGetUniversalAxis1(joint, ax1);
844 addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
845 dampRotationalMotion (0.1);
846 dReal a = dJointGetUniversalAngle1(joint);
847 dReal r = dJointGetUniversalAngle1Rate(joint);
848 dReal diff = a - last_angle;
849 if (diff > M_PI) diff -= 2*M_PI;
850 if (diff < -M_PI) diff += 2*M_PI;
851 dReal er = diff / STEPSIZE; // estimated rate
852 last_angle = a;
853 return fabs(r - er) * 2e3;
854 }
855
856 case 732:{
857 dVector3 ax1;
858 static dReal last_angle = 0;
859 dJointGetUniversalAxis1(joint, ax1);
860 addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
861 dampRotationalMotion (0.1);
862 dReal a = dJointGetUniversalAngle2(joint);
863 dReal r = dJointGetUniversalAngle2Rate(joint);
864 dReal diff = a - last_angle;
865 if (diff > M_PI) diff -= 2*M_PI;
866 if (diff < -M_PI) diff += 2*M_PI;
867 dReal er = diff / STEPSIZE; // estimated rate
868 last_angle = a;
869 return fabs(r - er) * 1e10;
870 }
871
872 case 740:{
873 dVector3 ax1, ax2;
874 dJointGetUniversalAxis1(joint, ax1);
875 dJointGetUniversalAxis2(joint, ax2);
876 addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
877 dampRotationalMotion (0.1);
878 return fabs(10*dDOT(ax1, ax2));
879 }
880
881 case 741:{
882 dVector3 ax2;
883 static dReal last_angle = 0;
884 dJointGetUniversalAxis2(joint, ax2);
885 addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
886 dampRotationalMotion (0.1);
887 dReal a = dJointGetUniversalAngle1(joint);
888 dReal r = dJointGetUniversalAngle1Rate(joint);
889 dReal diff = a - last_angle;
890 if (diff > M_PI) diff -= 2*M_PI;
891 if (diff < -M_PI) diff += 2*M_PI;
892 dReal er = diff / STEPSIZE; // estimated rate
893 last_angle = a;
894 return fabs(r - er) * 1e10;
895 }
896
897 case 742:{
898 dVector3 ax2;
899 static dReal last_angle = 0;
900 dJointGetUniversalAxis2(joint, ax2);
901 addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
902 dampRotationalMotion (0.1);
903 dReal a = dJointGetUniversalAngle2(joint);
904 dReal r = dJointGetUniversalAngle2Rate(joint);
905 dReal diff = a - last_angle;
906 if (diff > M_PI) diff -= 2*M_PI;
907 if (diff < -M_PI) diff += 2*M_PI;
908 dReal er = diff / STEPSIZE; // estimated rate
909 last_angle = a;
910 return fabs(r - er) * 1e4;
911 }
912
913 // ********** slider joint
914 case 801:
915 case 803:
916 addSpringForce (0.25);
917 return dInfinity;
918
919 case 802:
920 case 804: {
921 static dReal a = 0;
922 dBodyAddTorque (body[0], 0, 0.01*cos(1.5708*a), 0);
923 a += 0.01;
924 return dInfinity;
925 }
926
927 case 805:
928 addOscillatingForce (0.1);
929 return dInfinity;
930 }
931
932
933 return dInfinity;
934}
935
936//****************************************************************************
937// simulation stuff common to all the tests
938
939// start simulation - set viewpoint
940
941static void start()
942{
943 static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
944 static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
945 dsSetViewpoint (xyz,hpr);
946}
947
948
949// simulation loop
950
951static void simLoop (int pause)
952{
953 // stop after a given number of iterations, as long as we are not in
954 // interactive mode
955 if (cmd_graphics && !cmd_interactive &&
956 (iteration >= max_iterations)) {
957 dsStop();
958 return;
959 }
960 iteration++;
961
962 if (!pause) {
963 // do stuff for this test and check to see if the joint is behaving well
964 dReal error = doStuffAndGetError (test_num);
965 if (error > max_error) max_error = error;
966 if (cmd_interactive && error < dInfinity) {
967 printf ("scaled error = %.4e\n",error);
968 }
969
970 // take a step
971 dWorldStep (world,STEPSIZE);
972
973 // occasionally re-orient the first body to create a deliberate error.
974 if (cmd_occasional_error) {
975 static int count = 0;
976 if ((count % 20)==0) {
977 // randomly adjust orientation of body[0]
978 const dReal *R1;
979 dMatrix3 R2,R3;
980 R1 = dBodyGetRotation (body[0]);
981 dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
982 dRandReal()-0.5,dRandReal()-0.5);
983 dMultiply0 (R3,R1,R2,3,3,3);
984 dBodySetRotation (body[0],R3);
985
986 // randomly adjust position of body[0]
987 const dReal *pos = dBodyGetPosition (body[0]);
988 dBodySetPosition (body[0],
989 pos[0]+0.2*(dRandReal()-0.5),
990 pos[1]+0.2*(dRandReal()-0.5),
991 pos[2]+0.2*(dRandReal()-0.5));
992 }
993 count++;
994 }
995 }
996
997 if (cmd_graphics) {
998 dReal sides1[3] = {SIDE,SIDE,SIDE};
999 dReal sides2[3] = {SIDE*0.99f,SIDE*0.99f,SIDE*0.99f};
1000 dsSetTexture (DS_WOOD);
1001 dsSetColor (1,1,0);
1002 dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
1003 if (body[1]) {
1004 dsSetColor (0,1,1);
1005 dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
1006 }
1007 }
1008}
1009
1010//****************************************************************************
1011// conduct a specific test, and report the results
1012
1013void doTest (int argc, char **argv, int n, int fatal_if_bad_n)
1014{
1015 test_num = n;
1016 iteration = 0;
1017 max_iterations = 300;
1018 max_error = 0;
1019
1020 if (! setupTest (n)) {
1021 if (fatal_if_bad_n) dError (0,"bad test number");
1022 return;
1023 }
1024
1025 // setup pointers to drawstuff callback functions
1026 dsFunctions fn;
1027 fn.version = DS_VERSION;
1028 fn.start = &start;
1029 fn.step = &simLoop;
1030 fn.command = 0;
1031 fn.stop = 0;
1032 if (cmd_path_to_textures)
1033 fn.path_to_textures = cmd_path_to_textures;
1034 else
1035 fn.path_to_textures = "../../drawstuff/textures";
1036
1037 // run simulation
1038 if (cmd_graphics) {
1039 dsSimulationLoop (argc,argv,352,288,&fn);
1040 }
1041 else {
1042 for (int i=0; i < max_iterations; i++) simLoop (0);
1043 }
1044 dWorldDestroy (world);
1045 body[0] = 0;
1046 body[1] = 0;
1047 joint = 0;
1048
1049 // print results
1050 printf ("test %d: ",n);
1051 if (max_error == dInfinity) printf ("error not computed\n");
1052 else {
1053 printf ("max scaled error = %.4e",max_error);
1054 if (max_error < 1) printf (" - passed\n");
1055 else printf (" - FAILED\n");
1056 }
1057}
1058
1059//****************************************************************************
1060// main
1061
1062int main (int argc, char **argv)
1063{
1064 int i;
1065 dInitODE();
1066
1067 // process the command line args. anything that starts with `-' is assumed
1068 // to be a drawstuff argument.
1069 for (i=1; i<argc; i++) {
1070 if ( argv[i][0]=='-' && argv[i][1]=='i' && argv[i][2]==0) cmd_interactive = 1;
1071 else if ( argv[i][0]=='-' && argv[i][1]=='g' && argv[i][2]==0) cmd_graphics = 0;
1072 else if ( argv[i][0]=='-' && argv[i][1]=='e' && argv[i][2]==0) cmd_graphics = 0;
1073 else if ( argv[i][0]=='-' && argv[i][1]=='n' && isdigit(argv[i][2]) ) {
1074 char *endptr;
1075 long int n = strtol (&(argv[i][2]),&endptr,10);
1076 if (*endptr == 0) cmd_test_num = n;
1077 }
1078 else
1079 cmd_path_to_textures = argv[i];
1080 }
1081
1082 // do the tests
1083 if (cmd_test_num == -1) {
1084 for (i=0; i<NUM_JOINTS*100; i++) doTest (argc,argv,i,0);
1085 }
1086 else {
1087 doTest (argc,argv,cmd_test_num,1);
1088 }
1089
1090 dCloseODE();
1091 return 0;
1092}
diff --git a/libraries/ode-0.9/ode/demo/demo_motor.cpp b/libraries/ode-0.9/ode/demo/demo_motor.cpp
deleted file mode 100644
index 655da0c..0000000
--- a/libraries/ode-0.9/ode/demo/demo_motor.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30// select correct drawing functions
31#ifdef dDOUBLE
32#define dsDrawBox dsDrawBoxD
33#endif
34
35
36// some constants
37#define SIDE (0.5f) // side length of a box
38#define MASS (1.0) // mass of a box
39
40
41// dynamics and collision objects
42static dWorldID world;
43static dBodyID body[2];
44static dGeomID geom[2];
45static dJointID lmotor[2];
46static dJointID amotor[2];
47static dSpaceID space;
48static dJointGroupID contactgroup;
49
50
51// start simulation - set viewpoint
52
53static void start()
54{
55 static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
56 static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
57 dsSetViewpoint (xyz,hpr);
58 printf ("Press 'q,a,z' to control one axis of lmotor connectiong two bodies. (q is +,a is 0, z is -)\n");
59 printf ("Press 'w,e,r' to control one axis of lmotor connectiong first body with world. (w is +,e is 0, r is -)\n");
60}
61
62
63// called when a key pressed
64
65static void command (int cmd)
66{
67 if (cmd == 'q' || cmd == 'Q') {
68 dJointSetLMotorParam(lmotor[0],dParamVel,0);
69 dJointSetLMotorParam(lmotor[0],dParamVel2,0);
70 dJointSetLMotorParam(lmotor[0],dParamVel3,0.1);
71 } else if (cmd == 'a' || cmd == 'A') {
72 dJointSetLMotorParam(lmotor[0],dParamVel,0);
73 dJointSetLMotorParam(lmotor[0],dParamVel2,0);
74 dJointSetLMotorParam(lmotor[0],dParamVel3,0);
75 } else if (cmd == 'z' || cmd == 'Z') {
76 dJointSetLMotorParam(lmotor[0],dParamVel,0);
77 dJointSetLMotorParam(lmotor[0],dParamVel2,0);
78 dJointSetLMotorParam(lmotor[0],dParamVel3,-0.1);
79 } else if (cmd == 'w' || cmd == 'W') {
80 dJointSetLMotorParam(lmotor[1],dParamVel,0.1);
81 dJointSetLMotorParam(lmotor[1],dParamVel2,0);
82 dJointSetLMotorParam(lmotor[1],dParamVel3,0);
83 } else if (cmd == 'e' || cmd == 'E') {
84 dJointSetLMotorParam(lmotor[1],dParamVel,0);
85 dJointSetLMotorParam(lmotor[1],dParamVel2,0);
86 dJointSetLMotorParam(lmotor[1],dParamVel3,0);
87 } else if (cmd == 'r' || cmd == 'R') {
88 dJointSetLMotorParam(lmotor[1],dParamVel,-0.1);
89 dJointSetLMotorParam(lmotor[1],dParamVel2,0);
90 dJointSetLMotorParam(lmotor[1],dParamVel3,0);
91 }
92
93}
94
95
96
97static void nearCallback (void *data, dGeomID o1, dGeomID o2)
98{
99 // exit without doing anything if the two bodies are connected by a joint
100 dBodyID b1 = dGeomGetBody(o1);
101 dBodyID b2 = dGeomGetBody(o2);
102
103 dContact contact;
104 contact.surface.mode = 0;
105 contact.surface.mu = dInfinity;
106 if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
107 dJointID c = dJointCreateContact (world,contactgroup,&contact);
108 dJointAttach (c,b1,b2);
109 }
110}
111
112// simulation loop
113
114static void simLoop (int pause)
115{
116 if (!pause) {
117 dSpaceCollide(space,0,&nearCallback);
118 dWorldQuickStep (world,0.05);
119 dJointGroupEmpty(contactgroup);
120 }
121
122 dReal sides1[3];
123 dGeomBoxGetLengths(geom[0], sides1);
124 dReal sides2[3];
125 dGeomBoxGetLengths(geom[1], sides2);
126 dsSetTexture (DS_WOOD);
127 dsSetColor (1,1,0);
128 dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
129 dsSetColor (0,1,1);
130 dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
131}
132
133
134int main (int argc, char **argv)
135{
136 // setup pointers to drawstuff callback functions
137 dsFunctions fn;
138 fn.version = DS_VERSION;
139 fn.start = &start;
140 fn.step = &simLoop;
141 fn.command = &command;
142 fn.stop = 0;
143 fn.path_to_textures = "../../drawstuff/textures";
144 if(argc>=2)
145 {
146 fn.path_to_textures = argv[1];
147 }
148
149 // create world
150 dInitODE();
151 contactgroup = dJointGroupCreate(0);
152 world = dWorldCreate();
153 space = dSimpleSpaceCreate(0);
154 dMass m;
155 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
156 dMassAdjust (&m,MASS);
157
158 body[0] = dBodyCreate (world);
159 dBodySetMass (body[0],&m);
160 dBodySetPosition (body[0],0,0,1);
161 geom[0] = dCreateBox(space,SIDE,SIDE,SIDE);
162 body[1] = dBodyCreate (world);
163 dBodySetMass (body[1],&m);
164 dBodySetPosition (body[1],0,0,2);
165 geom[1] = dCreateBox(space,SIDE,SIDE,SIDE);
166
167 dGeomSetBody(geom[0],body[0]);
168 dGeomSetBody(geom[1],body[1]);
169
170 lmotor[0] = dJointCreateLMotor (world,0);
171 dJointAttach (lmotor[0],body[0],body[1]);
172 lmotor[1] = dJointCreateLMotor (world,0);
173 dJointAttach (lmotor[1],body[0],0);
174 amotor[0] = dJointCreateAMotor(world,0);
175 dJointAttach(amotor[0], body[0],body[1]);
176 amotor[1] = dJointCreateAMotor(world,0);
177 dJointAttach(amotor[1], body[0], 0);
178
179 for (int i=0; i<2; i++) {
180 dJointSetAMotorNumAxes(amotor[i], 3);
181 dJointSetAMotorAxis(amotor[i],0,1,1,0,0);
182 dJointSetAMotorAxis(amotor[i],1,1,0,1,0);
183 dJointSetAMotorAxis(amotor[i],2,1,0,0,1);
184 dJointSetAMotorParam(amotor[i],dParamFMax,0.00001);
185 dJointSetAMotorParam(amotor[i],dParamFMax2,0.00001);
186 dJointSetAMotorParam(amotor[i],dParamFMax3,0.00001);
187
188 dJointSetAMotorParam(amotor[i],dParamVel,0);
189 dJointSetAMotorParam(amotor[i],dParamVel2,0);
190 dJointSetAMotorParam(amotor[i],dParamVel3,0);
191
192 dJointSetLMotorNumAxes(lmotor[i],3);
193 dJointSetLMotorAxis(lmotor[i],0,1,1,0,0);
194 dJointSetLMotorAxis(lmotor[i],1,1,0,1,0);
195 dJointSetLMotorAxis(lmotor[i],2,1,0,0,1);
196
197 dJointSetLMotorParam(lmotor[i],dParamFMax,0.0001);
198 dJointSetLMotorParam(lmotor[i],dParamFMax2,0.0001);
199 dJointSetLMotorParam(lmotor[i],dParamFMax3,0.0001);
200 }
201
202 // run simulation
203 dsSimulationLoop (argc,argv,352,288,&fn);
204
205 dJointGroupDestroy(contactgroup);
206 dSpaceDestroy (space);
207 dWorldDestroy (world);
208 dCloseODE();
209 return 0;
210}
diff --git a/libraries/ode-0.9/ode/demo/demo_moving_trimesh.cpp b/libraries/ode-0.9/ode/demo/demo_moving_trimesh.cpp
deleted file mode 100644
index 3d03020..0000000
--- a/libraries/ode-0.9/ode/demo/demo_moving_trimesh.cpp
+++ /dev/null
@@ -1,1944 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30// select correct drawing functions
31
32#ifdef dDOUBLE
33#define dsDrawBox dsDrawBoxD
34#define dsDrawSphere dsDrawSphereD
35#define dsDrawCylinder dsDrawCylinderD
36#define dsDrawCapsule dsDrawCapsuleD
37#define dsDrawLine dsDrawLineD
38#define dsDrawTriangle dsDrawTriangleD
39#endif
40
41
42// some constants
43
44#define NUM 200 // max number of objects
45#define DENSITY (5.0) // density of all objects
46#define GPB 3 // maximum number of geometries per body
47#define MAX_CONTACTS 64 // maximum number of contact points per body
48
49
50// dynamics and collision objects
51
52struct MyObject {
53 dBodyID body; // the body
54 dGeomID geom[GPB]; // geometries representing this body
55
56 // Trimesh only - double buffered matrices for 'last transform' setup
57 dReal matrix_dblbuff[ 16 * 2 ];
58 int last_matrix_index;
59};
60
61static int num=0; // number of objects in simulation
62static int nextobj=0; // next object to recycle if num==NUM
63static dWorldID world;
64static dSpaceID space;
65static MyObject obj[NUM];
66static dJointGroupID contactgroup;
67static int selected = -1; // selected object
68static int show_aabb = 0; // show geom AABBs?
69static int show_contacts = 0; // show contact points?
70static int random_pos = 1; // drop objects from random position?
71
72// Bunny mesh ripped from Opcode
73const int VertexCount = 453;
74const int IndexCount = 902 * 3;
75
76typedef dReal dVector3R[3];
77
78dGeomID TriMesh1;
79dGeomID TriMesh2;
80static dTriMeshDataID TriData1, TriData2; // reusable static trimesh data
81
82float Vertices[VertexCount * 3] = {
83 REAL(-0.334392), REAL(0.133007), REAL(0.062259),
84 REAL(-0.350189), REAL(0.150354), REAL(-0.147769),
85 REAL(-0.234201), REAL(0.343811), REAL(-0.174307),
86 REAL(-0.200259), REAL(0.285207), REAL(0.093749),
87 REAL(0.003520), REAL(0.475208), REAL(-0.159365),
88 REAL(0.001856), REAL(0.419203), REAL(0.098582),
89 REAL(-0.252802), REAL(0.093666), REAL(0.237538),
90 REAL(-0.162901), REAL(0.237984), REAL(0.206905),
91 REAL(0.000865), REAL(0.318141), REAL(0.235370),
92 REAL(-0.414624), REAL(0.164083), REAL(-0.278254),
93 REAL(-0.262213), REAL(0.357334), REAL(-0.293246),
94 REAL(0.004628), REAL(0.482694), REAL(-0.338626),
95 REAL(-0.402162), REAL(0.133528), REAL(-0.443247),
96 REAL(-0.243781), REAL(0.324275), REAL(-0.436763),
97 REAL(0.005293), REAL(0.437592), REAL(-0.458332),
98 REAL(-0.339884), REAL(-0.041150), REAL(-0.668211),
99 REAL(-0.248382), REAL(0.255825), REAL(-0.627493),
100 REAL(0.006261), REAL(0.376103), REAL(-0.631506),
101 REAL(-0.216201), REAL(-0.126776), REAL(-0.886936),
102 REAL(-0.171075), REAL(0.011544), REAL(-0.881386),
103 REAL(-0.181074), REAL(0.098223), REAL(-0.814779),
104 REAL(-0.119891), REAL(0.218786), REAL(-0.760153),
105 REAL(-0.078895), REAL(0.276780), REAL(-0.739281),
106 REAL(0.006801), REAL(0.310959), REAL(-0.735661),
107 REAL(-0.168842), REAL(0.102387), REAL(-0.920381),
108 REAL(-0.104072), REAL(0.177278), REAL(-0.952530),
109 REAL(-0.129704), REAL(0.211848), REAL(-0.836678),
110 REAL(-0.099875), REAL(0.310931), REAL(-0.799381),
111 REAL(0.007237), REAL(0.361687), REAL(-0.794439),
112 REAL(-0.077913), REAL(0.258753), REAL(-0.921640),
113 REAL(0.007957), REAL(0.282241), REAL(-0.931680),
114 REAL(-0.252222), REAL(-0.550401), REAL(-0.557810),
115 REAL(-0.267633), REAL(-0.603419), REAL(-0.655209),
116 REAL(-0.446838), REAL(-0.118517), REAL(-0.466159),
117 REAL(-0.459488), REAL(-0.093017), REAL(-0.311341),
118 REAL(-0.370645), REAL(-0.100108), REAL(-0.159454),
119 REAL(-0.371984), REAL(-0.091991), REAL(-0.011044),
120 REAL(-0.328945), REAL(-0.098269), REAL(0.088659),
121 REAL(-0.282452), REAL(-0.018862), REAL(0.311501),
122 REAL(-0.352403), REAL(-0.131341), REAL(0.144902),
123 REAL(-0.364126), REAL(-0.200299), REAL(0.202388),
124 REAL(-0.283965), REAL(-0.231869), REAL(0.023668),
125 REAL(-0.298943), REAL(-0.155218), REAL(0.369716),
126 REAL(-0.293787), REAL(-0.121856), REAL(0.419097),
127 REAL(-0.290163), REAL(-0.290797), REAL(0.107824),
128 REAL(-0.264165), REAL(-0.272849), REAL(0.036347),
129 REAL(-0.228567), REAL(-0.372573), REAL(0.290309),
130 REAL(-0.190431), REAL(-0.286997), REAL(0.421917),
131 REAL(-0.191039), REAL(-0.240973), REAL(0.507118),
132 REAL(-0.287272), REAL(-0.276431), REAL(-0.065444),
133 REAL(-0.295675), REAL(-0.280818), REAL(-0.174200),
134 REAL(-0.399537), REAL(-0.313131), REAL(-0.376167),
135 REAL(-0.392666), REAL(-0.488581), REAL(-0.427494),
136 REAL(-0.331669), REAL(-0.570185), REAL(-0.466054),
137 REAL(-0.282290), REAL(-0.618140), REAL(-0.589220),
138 REAL(-0.374238), REAL(-0.594882), REAL(-0.323298),
139 REAL(-0.381071), REAL(-0.629723), REAL(-0.350777),
140 REAL(-0.382112), REAL(-0.624060), REAL(-0.221577),
141 REAL(-0.272701), REAL(-0.566522), REAL(0.259157),
142 REAL(-0.256702), REAL(-0.663406), REAL(0.286079),
143 REAL(-0.280948), REAL(-0.428359), REAL(0.055790),
144 REAL(-0.184974), REAL(-0.508894), REAL(0.326265),
145 REAL(-0.279971), REAL(-0.526918), REAL(0.395319),
146 REAL(-0.282599), REAL(-0.663393), REAL(0.412411),
147 REAL(-0.188329), REAL(-0.475093), REAL(0.417954),
148 REAL(-0.263384), REAL(-0.663396), REAL(0.466604),
149 REAL(-0.209063), REAL(-0.663393), REAL(0.509344),
150 REAL(-0.002044), REAL(-0.319624), REAL(0.553078),
151 REAL(-0.001266), REAL(-0.371260), REAL(0.413296),
152 REAL(-0.219753), REAL(-0.339762), REAL(-0.040921),
153 REAL(-0.256986), REAL(-0.282511), REAL(-0.006349),
154 REAL(-0.271706), REAL(-0.260881), REAL(0.001764),
155 REAL(-0.091191), REAL(-0.419184), REAL(-0.045912),
156 REAL(-0.114944), REAL(-0.429752), REAL(-0.124739),
157 REAL(-0.113970), REAL(-0.382987), REAL(-0.188540),
158 REAL(-0.243012), REAL(-0.464942), REAL(-0.242850),
159 REAL(-0.314815), REAL(-0.505402), REAL(-0.324768),
160 REAL(0.002774), REAL(-0.437526), REAL(-0.262766),
161 REAL(-0.072625), REAL(-0.417748), REAL(-0.221440),
162 REAL(-0.160112), REAL(-0.476932), REAL(-0.293450),
163 REAL(0.003859), REAL(-0.453425), REAL(-0.443916),
164 REAL(-0.120363), REAL(-0.581567), REAL(-0.438689),
165 REAL(-0.091499), REAL(-0.584191), REAL(-0.294511),
166 REAL(-0.116469), REAL(-0.599861), REAL(-0.188308),
167 REAL(-0.208032), REAL(-0.513640), REAL(-0.134649),
168 REAL(-0.235749), REAL(-0.610017), REAL(-0.040939),
169 REAL(-0.344916), REAL(-0.622487), REAL(-0.085380),
170 REAL(-0.336401), REAL(-0.531864), REAL(-0.212298),
171 REAL(0.001961), REAL(-0.459550), REAL(-0.135547),
172 REAL(-0.058296), REAL(-0.430536), REAL(-0.043440),
173 REAL(0.001378), REAL(-0.449511), REAL(-0.037762),
174 REAL(-0.130135), REAL(-0.510222), REAL(0.079144),
175 REAL(0.000142), REAL(-0.477549), REAL(0.157064),
176 REAL(-0.114284), REAL(-0.453206), REAL(0.304397),
177 REAL(-0.000592), REAL(-0.443558), REAL(0.285401),
178 REAL(-0.056215), REAL(-0.663402), REAL(0.326073),
179 REAL(-0.026248), REAL(-0.568010), REAL(0.273318),
180 REAL(-0.049261), REAL(-0.531064), REAL(0.389854),
181 REAL(-0.127096), REAL(-0.663398), REAL(0.479316),
182 REAL(-0.058384), REAL(-0.663401), REAL(0.372891),
183 REAL(-0.303961), REAL(0.054199), REAL(0.625921),
184 REAL(-0.268594), REAL(0.193403), REAL(0.502766),
185 REAL(-0.277159), REAL(0.126123), REAL(0.443289),
186 REAL(-0.287605), REAL(-0.005722), REAL(0.531844),
187 REAL(-0.231396), REAL(-0.121289), REAL(0.587387),
188 REAL(-0.253475), REAL(-0.081797), REAL(0.756541),
189 REAL(-0.195164), REAL(-0.137969), REAL(0.728011),
190 REAL(-0.167673), REAL(-0.156573), REAL(0.609388),
191 REAL(-0.145917), REAL(-0.169029), REAL(0.697600),
192 REAL(-0.077776), REAL(-0.214247), REAL(0.622586),
193 REAL(-0.076873), REAL(-0.214971), REAL(0.696301),
194 REAL(-0.002341), REAL(-0.233135), REAL(0.622859),
195 REAL(-0.002730), REAL(-0.213526), REAL(0.691267),
196 REAL(-0.003136), REAL(-0.192628), REAL(0.762731),
197 REAL(-0.056136), REAL(-0.201222), REAL(0.763806),
198 REAL(-0.114589), REAL(-0.166192), REAL(0.770723),
199 REAL(-0.155145), REAL(-0.129632), REAL(0.791738),
200 REAL(-0.183611), REAL(-0.058705), REAL(0.847012),
201 REAL(-0.165562), REAL(0.001980), REAL(0.833386),
202 REAL(-0.220084), REAL(0.019914), REAL(0.768935),
203 REAL(-0.255730), REAL(0.090306), REAL(0.670782),
204 REAL(-0.255594), REAL(0.113833), REAL(0.663389),
205 REAL(-0.226380), REAL(0.212655), REAL(0.617740),
206 REAL(-0.003367), REAL(-0.195342), REAL(0.799680),
207 REAL(-0.029743), REAL(-0.210508), REAL(0.827180),
208 REAL(-0.003818), REAL(-0.194783), REAL(0.873636),
209 REAL(-0.004116), REAL(-0.157907), REAL(0.931268),
210 REAL(-0.031280), REAL(-0.184555), REAL(0.889476),
211 REAL(-0.059885), REAL(-0.184448), REAL(0.841330),
212 REAL(-0.135333), REAL(-0.164332), REAL(0.878200),
213 REAL(-0.085574), REAL(-0.170948), REAL(0.925547),
214 REAL(-0.163833), REAL(-0.094170), REAL(0.897114),
215 REAL(-0.138444), REAL(-0.104250), REAL(0.945975),
216 REAL(-0.083497), REAL(-0.084934), REAL(0.979607),
217 REAL(-0.004433), REAL(-0.146642), REAL(0.985872),
218 REAL(-0.150715), REAL(0.032650), REAL(0.884111),
219 REAL(-0.135892), REAL(-0.035520), REAL(0.945455),
220 REAL(-0.070612), REAL(0.036849), REAL(0.975733),
221 REAL(-0.004458), REAL(-0.042526), REAL(1.015670),
222 REAL(-0.004249), REAL(0.046042), REAL(1.003240),
223 REAL(-0.086969), REAL(0.133224), REAL(0.947633),
224 REAL(-0.003873), REAL(0.161605), REAL(0.970499),
225 REAL(-0.125544), REAL(0.140012), REAL(0.917678),
226 REAL(-0.125651), REAL(0.250246), REAL(0.857602),
227 REAL(-0.003127), REAL(0.284070), REAL(0.878870),
228 REAL(-0.159174), REAL(0.125726), REAL(0.888878),
229 REAL(-0.183807), REAL(0.196970), REAL(0.844480),
230 REAL(-0.159890), REAL(0.291736), REAL(0.732480),
231 REAL(-0.199495), REAL(0.207230), REAL(0.779864),
232 REAL(-0.206182), REAL(0.164608), REAL(0.693257),
233 REAL(-0.186315), REAL(0.160689), REAL(0.817193),
234 REAL(-0.192827), REAL(0.166706), REAL(0.782271),
235 REAL(-0.175112), REAL(0.110008), REAL(0.860621),
236 REAL(-0.161022), REAL(0.057420), REAL(0.855111),
237 REAL(-0.172319), REAL(0.036155), REAL(0.816189),
238 REAL(-0.190318), REAL(0.064083), REAL(0.760605),
239 REAL(-0.195072), REAL(0.129179), REAL(0.731104),
240 REAL(-0.203126), REAL(0.410287), REAL(0.680536),
241 REAL(-0.216677), REAL(0.309274), REAL(0.642272),
242 REAL(-0.241515), REAL(0.311485), REAL(0.587832),
243 REAL(-0.002209), REAL(0.366663), REAL(0.749413),
244 REAL(-0.088230), REAL(0.396265), REAL(0.678635),
245 REAL(-0.170147), REAL(0.109517), REAL(0.840784),
246 REAL(-0.160521), REAL(0.067766), REAL(0.830650),
247 REAL(-0.181546), REAL(0.139805), REAL(0.812146),
248 REAL(-0.180495), REAL(0.148568), REAL(0.776087),
249 REAL(-0.180255), REAL(0.129125), REAL(0.744192),
250 REAL(-0.186298), REAL(0.078308), REAL(0.769352),
251 REAL(-0.167622), REAL(0.060539), REAL(0.806675),
252 REAL(-0.189876), REAL(0.102760), REAL(0.802582),
253 REAL(-0.108340), REAL(0.455446), REAL(0.657174),
254 REAL(-0.241585), REAL(0.527592), REAL(0.669296),
255 REAL(-0.265676), REAL(0.513366), REAL(0.634594),
256 REAL(-0.203073), REAL(0.478550), REAL(0.581526),
257 REAL(-0.266772), REAL(0.642330), REAL(0.602061),
258 REAL(-0.216961), REAL(0.564846), REAL(0.535435),
259 REAL(-0.202210), REAL(0.525495), REAL(0.475944),
260 REAL(-0.193888), REAL(0.467925), REAL(0.520606),
261 REAL(-0.265837), REAL(0.757267), REAL(0.500933),
262 REAL(-0.240306), REAL(0.653440), REAL(0.463215),
263 REAL(-0.309239), REAL(0.776868), REAL(0.304726),
264 REAL(-0.271009), REAL(0.683094), REAL(0.382018),
265 REAL(-0.312111), REAL(0.671099), REAL(0.286687),
266 REAL(-0.268791), REAL(0.624342), REAL(0.377231),
267 REAL(-0.302457), REAL(0.533996), REAL(0.360289),
268 REAL(-0.263656), REAL(0.529310), REAL(0.412564),
269 REAL(-0.282311), REAL(0.415167), REAL(0.447666),
270 REAL(-0.239201), REAL(0.442096), REAL(0.495604),
271 REAL(-0.220043), REAL(0.569026), REAL(0.445877),
272 REAL(-0.001263), REAL(0.395631), REAL(0.602029),
273 REAL(-0.057345), REAL(0.442535), REAL(0.572224),
274 REAL(-0.088927), REAL(0.506333), REAL(0.529106),
275 REAL(-0.125738), REAL(0.535076), REAL(0.612913),
276 REAL(-0.126251), REAL(0.577170), REAL(0.483159),
277 REAL(-0.149594), REAL(0.611520), REAL(0.557731),
278 REAL(-0.163188), REAL(0.660791), REAL(0.491080),
279 REAL(-0.172482), REAL(0.663387), REAL(0.415416),
280 REAL(-0.160464), REAL(0.591710), REAL(0.370659),
281 REAL(-0.156445), REAL(0.536396), REAL(0.378302),
282 REAL(-0.136496), REAL(0.444358), REAL(0.425226),
283 REAL(-0.095564), REAL(0.373768), REAL(0.473659),
284 REAL(-0.104146), REAL(0.315912), REAL(0.498104),
285 REAL(-0.000496), REAL(0.384194), REAL(0.473817),
286 REAL(-0.000183), REAL(0.297770), REAL(0.401486),
287 REAL(-0.129042), REAL(0.270145), REAL(0.434495),
288 REAL(0.000100), REAL(0.272963), REAL(0.349138),
289 REAL(-0.113060), REAL(0.236984), REAL(0.385554),
290 REAL(0.007260), REAL(0.016311), REAL(-0.883396),
291 REAL(0.007865), REAL(0.122104), REAL(-0.956137),
292 REAL(-0.032842), REAL(0.115282), REAL(-0.953252),
293 REAL(-0.089115), REAL(0.108449), REAL(-0.950317),
294 REAL(-0.047440), REAL(0.014729), REAL(-0.882756),
295 REAL(-0.104458), REAL(0.013137), REAL(-0.882070),
296 REAL(-0.086439), REAL(-0.584866), REAL(-0.608343),
297 REAL(-0.115026), REAL(-0.662605), REAL(-0.436732),
298 REAL(-0.071683), REAL(-0.665372), REAL(-0.606385),
299 REAL(-0.257884), REAL(-0.665381), REAL(-0.658052),
300 REAL(-0.272542), REAL(-0.665381), REAL(-0.592063),
301 REAL(-0.371322), REAL(-0.665382), REAL(-0.353620),
302 REAL(-0.372362), REAL(-0.665381), REAL(-0.224420),
303 REAL(-0.335166), REAL(-0.665380), REAL(-0.078623),
304 REAL(-0.225999), REAL(-0.665375), REAL(-0.038981),
305 REAL(-0.106719), REAL(-0.665374), REAL(-0.186351),
306 REAL(-0.081749), REAL(-0.665372), REAL(-0.292554),
307 REAL(0.006943), REAL(-0.091505), REAL(-0.858354),
308 REAL(0.006117), REAL(-0.280985), REAL(-0.769967),
309 REAL(0.004495), REAL(-0.502360), REAL(-0.559799),
310 REAL(-0.198638), REAL(-0.302135), REAL(-0.845816),
311 REAL(-0.237395), REAL(-0.542544), REAL(-0.587188),
312 REAL(-0.270001), REAL(-0.279489), REAL(-0.669861),
313 REAL(-0.134547), REAL(-0.119852), REAL(-0.959004),
314 REAL(-0.052088), REAL(-0.122463), REAL(-0.944549),
315 REAL(-0.124463), REAL(-0.293508), REAL(-0.899566),
316 REAL(-0.047616), REAL(-0.289643), REAL(-0.879292),
317 REAL(-0.168595), REAL(-0.529132), REAL(-0.654931),
318 REAL(-0.099793), REAL(-0.515719), REAL(-0.645873),
319 REAL(-0.186168), REAL(-0.605282), REAL(-0.724690),
320 REAL(-0.112970), REAL(-0.583097), REAL(-0.707469),
321 REAL(-0.108152), REAL(-0.665375), REAL(-0.700408),
322 REAL(-0.183019), REAL(-0.665378), REAL(-0.717630),
323 REAL(-0.349529), REAL(-0.334459), REAL(-0.511985),
324 REAL(-0.141182), REAL(-0.437705), REAL(-0.798194),
325 REAL(-0.212670), REAL(-0.448725), REAL(-0.737447),
326 REAL(-0.261111), REAL(-0.414945), REAL(-0.613835),
327 REAL(-0.077364), REAL(-0.431480), REAL(-0.778113),
328 REAL(0.005174), REAL(-0.425277), REAL(-0.651592),
329 REAL(0.089236), REAL(-0.431732), REAL(-0.777093),
330 REAL(0.271006), REAL(-0.415749), REAL(-0.610577),
331 REAL(0.223981), REAL(-0.449384), REAL(-0.734774),
332 REAL(0.153275), REAL(-0.438150), REAL(-0.796391),
333 REAL(0.358414), REAL(-0.335529), REAL(-0.507649),
334 REAL(0.193434), REAL(-0.665946), REAL(-0.715325),
335 REAL(0.118363), REAL(-0.665717), REAL(-0.699021),
336 REAL(0.123515), REAL(-0.583454), REAL(-0.706020),
337 REAL(0.196851), REAL(-0.605860), REAL(-0.722345),
338 REAL(0.109788), REAL(-0.516035), REAL(-0.644590),
339 REAL(0.178656), REAL(-0.529656), REAL(-0.652804),
340 REAL(0.061157), REAL(-0.289807), REAL(-0.878626),
341 REAL(0.138234), REAL(-0.293905), REAL(-0.897958),
342 REAL(0.066933), REAL(-0.122643), REAL(-0.943820),
343 REAL(0.149571), REAL(-0.120281), REAL(-0.957264),
344 REAL(0.280989), REAL(-0.280321), REAL(-0.666487),
345 REAL(0.246581), REAL(-0.543275), REAL(-0.584224),
346 REAL(0.211720), REAL(-0.302754), REAL(-0.843303),
347 REAL(0.086966), REAL(-0.665627), REAL(-0.291520),
348 REAL(0.110634), REAL(-0.665702), REAL(-0.185021),
349 REAL(0.228099), REAL(-0.666061), REAL(-0.036201),
350 REAL(0.337743), REAL(-0.666396), REAL(-0.074503),
351 REAL(0.376722), REAL(-0.666513), REAL(-0.219833),
352 REAL(0.377265), REAL(-0.666513), REAL(-0.349036),
353 REAL(0.281411), REAL(-0.666217), REAL(-0.588670),
354 REAL(0.267564), REAL(-0.666174), REAL(-0.654834),
355 REAL(0.080745), REAL(-0.665602), REAL(-0.605452),
356 REAL(0.122016), REAL(-0.662963), REAL(-0.435280),
357 REAL(0.095767), REAL(-0.585141), REAL(-0.607228),
358 REAL(0.118944), REAL(0.012799), REAL(-0.880702),
359 REAL(0.061944), REAL(0.014564), REAL(-0.882086),
360 REAL(0.104725), REAL(0.108156), REAL(-0.949130),
361 REAL(0.048513), REAL(0.115159), REAL(-0.952753),
362 REAL(0.112696), REAL(0.236643), REAL(0.386937),
363 REAL(0.128177), REAL(0.269757), REAL(0.436071),
364 REAL(0.102643), REAL(0.315600), REAL(0.499370),
365 REAL(0.094535), REAL(0.373481), REAL(0.474824),
366 REAL(0.136270), REAL(0.443946), REAL(0.426895),
367 REAL(0.157071), REAL(0.535923), REAL(0.380222),
368 REAL(0.161350), REAL(0.591224), REAL(0.372630),
369 REAL(0.173035), REAL(0.662865), REAL(0.417531),
370 REAL(0.162808), REAL(0.660299), REAL(0.493077),
371 REAL(0.148250), REAL(0.611070), REAL(0.559555),
372 REAL(0.125719), REAL(0.576790), REAL(0.484702),
373 REAL(0.123489), REAL(0.534699), REAL(0.614440),
374 REAL(0.087621), REAL(0.506066), REAL(0.530188),
375 REAL(0.055321), REAL(0.442365), REAL(0.572915),
376 REAL(0.219936), REAL(0.568361), REAL(0.448571),
377 REAL(0.238099), REAL(0.441375), REAL(0.498528),
378 REAL(0.281711), REAL(0.414315), REAL(0.451121),
379 REAL(0.263833), REAL(0.528513), REAL(0.415794),
380 REAL(0.303284), REAL(0.533081), REAL(0.363998),
381 REAL(0.269687), REAL(0.623528), REAL(0.380528),
382 REAL(0.314255), REAL(0.670153), REAL(0.290524),
383 REAL(0.272023), REAL(0.682273), REAL(0.385343),
384 REAL(0.311480), REAL(0.775931), REAL(0.308527),
385 REAL(0.240239), REAL(0.652714), REAL(0.466159),
386 REAL(0.265619), REAL(0.756464), REAL(0.504187),
387 REAL(0.192562), REAL(0.467341), REAL(0.522972),
388 REAL(0.201605), REAL(0.524885), REAL(0.478417),
389 REAL(0.215743), REAL(0.564193), REAL(0.538084),
390 REAL(0.264969), REAL(0.641527), REAL(0.605317),
391 REAL(0.201031), REAL(0.477940), REAL(0.584002),
392 REAL(0.263086), REAL(0.512567), REAL(0.637832),
393 REAL(0.238615), REAL(0.526867), REAL(0.672237),
394 REAL(0.105309), REAL(0.455123), REAL(0.658482),
395 REAL(0.183993), REAL(0.102195), REAL(0.804872),
396 REAL(0.161563), REAL(0.060042), REAL(0.808692),
397 REAL(0.180748), REAL(0.077754), REAL(0.771600),
398 REAL(0.175168), REAL(0.128588), REAL(0.746368),
399 REAL(0.175075), REAL(0.148030), REAL(0.778264),
400 REAL(0.175658), REAL(0.139265), REAL(0.814333),
401 REAL(0.154191), REAL(0.067291), REAL(0.832578),
402 REAL(0.163818), REAL(0.109013), REAL(0.842830),
403 REAL(0.084760), REAL(0.396004), REAL(0.679695),
404 REAL(0.238888), REAL(0.310760), REAL(0.590775),
405 REAL(0.213380), REAL(0.308625), REAL(0.644905),
406 REAL(0.199666), REAL(0.409678), REAL(0.683003),
407 REAL(0.190143), REAL(0.128597), REAL(0.733463),
408 REAL(0.184833), REAL(0.063516), REAL(0.762902),
409 REAL(0.166070), REAL(0.035644), REAL(0.818261),
410 REAL(0.154361), REAL(0.056943), REAL(0.857042),
411 REAL(0.168542), REAL(0.109489), REAL(0.862725),
412 REAL(0.187387), REAL(0.166131), REAL(0.784599),
413 REAL(0.180428), REAL(0.160135), REAL(0.819438),
414 REAL(0.201823), REAL(0.163991), REAL(0.695756),
415 REAL(0.194206), REAL(0.206635), REAL(0.782275),
416 REAL(0.155438), REAL(0.291260), REAL(0.734412),
417 REAL(0.177696), REAL(0.196424), REAL(0.846693),
418 REAL(0.152305), REAL(0.125256), REAL(0.890786),
419 REAL(0.119546), REAL(0.249876), REAL(0.859104),
420 REAL(0.118369), REAL(0.139643), REAL(0.919173),
421 REAL(0.079410), REAL(0.132973), REAL(0.948652),
422 REAL(0.062419), REAL(0.036648), REAL(0.976547),
423 REAL(0.127847), REAL(-0.035919), REAL(0.947070),
424 REAL(0.143624), REAL(0.032206), REAL(0.885913),
425 REAL(0.074888), REAL(-0.085173), REAL(0.980577),
426 REAL(0.130184), REAL(-0.104656), REAL(0.947620),
427 REAL(0.156201), REAL(-0.094653), REAL(0.899074),
428 REAL(0.077366), REAL(-0.171194), REAL(0.926545),
429 REAL(0.127722), REAL(-0.164729), REAL(0.879810),
430 REAL(0.052670), REAL(-0.184618), REAL(0.842019),
431 REAL(0.023477), REAL(-0.184638), REAL(0.889811),
432 REAL(0.022626), REAL(-0.210587), REAL(0.827500),
433 REAL(0.223089), REAL(0.211976), REAL(0.620493),
434 REAL(0.251444), REAL(0.113067), REAL(0.666494),
435 REAL(0.251419), REAL(0.089540), REAL(0.673887),
436 REAL(0.214360), REAL(0.019258), REAL(0.771595),
437 REAL(0.158999), REAL(0.001490), REAL(0.835374),
438 REAL(0.176696), REAL(-0.059249), REAL(0.849218),
439 REAL(0.148696), REAL(-0.130091), REAL(0.793599),
440 REAL(0.108290), REAL(-0.166528), REAL(0.772088),
441 REAL(0.049820), REAL(-0.201382), REAL(0.764454),
442 REAL(0.071341), REAL(-0.215195), REAL(0.697209),
443 REAL(0.073148), REAL(-0.214475), REAL(0.623510),
444 REAL(0.140502), REAL(-0.169461), REAL(0.699354),
445 REAL(0.163374), REAL(-0.157073), REAL(0.611416),
446 REAL(0.189466), REAL(-0.138550), REAL(0.730366),
447 REAL(0.247593), REAL(-0.082554), REAL(0.759610),
448 REAL(0.227468), REAL(-0.121982), REAL(0.590197),
449 REAL(0.284702), REAL(-0.006586), REAL(0.535347),
450 REAL(0.275741), REAL(0.125287), REAL(0.446676),
451 REAL(0.266650), REAL(0.192594), REAL(0.506044),
452 REAL(0.300086), REAL(0.053287), REAL(0.629620),
453 REAL(0.055450), REAL(-0.663935), REAL(0.375065),
454 REAL(0.122854), REAL(-0.664138), REAL(0.482323),
455 REAL(0.046520), REAL(-0.531571), REAL(0.391918),
456 REAL(0.024824), REAL(-0.568450), REAL(0.275106),
457 REAL(0.053855), REAL(-0.663931), REAL(0.328224),
458 REAL(0.112829), REAL(-0.453549), REAL(0.305788),
459 REAL(0.131265), REAL(-0.510617), REAL(0.080746),
460 REAL(0.061174), REAL(-0.430716), REAL(-0.042710),
461 REAL(0.341019), REAL(-0.532887), REAL(-0.208150),
462 REAL(0.347705), REAL(-0.623533), REAL(-0.081139),
463 REAL(0.238040), REAL(-0.610732), REAL(-0.038037),
464 REAL(0.211764), REAL(-0.514274), REAL(-0.132078),
465 REAL(0.120605), REAL(-0.600219), REAL(-0.186856),
466 REAL(0.096985), REAL(-0.584476), REAL(-0.293357),
467 REAL(0.127621), REAL(-0.581941), REAL(-0.437170),
468 REAL(0.165902), REAL(-0.477425), REAL(-0.291453),
469 REAL(0.077720), REAL(-0.417975), REAL(-0.220519),
470 REAL(0.320892), REAL(-0.506363), REAL(-0.320874),
471 REAL(0.248214), REAL(-0.465684), REAL(-0.239842),
472 REAL(0.118764), REAL(-0.383338), REAL(-0.187114),
473 REAL(0.118816), REAL(-0.430106), REAL(-0.123307),
474 REAL(0.094131), REAL(-0.419464), REAL(-0.044777),
475 REAL(0.274526), REAL(-0.261706), REAL(0.005110),
476 REAL(0.259842), REAL(-0.283292), REAL(-0.003185),
477 REAL(0.222861), REAL(-0.340431), REAL(-0.038210),
478 REAL(0.204445), REAL(-0.664380), REAL(0.513353),
479 REAL(0.259286), REAL(-0.664547), REAL(0.471281),
480 REAL(0.185402), REAL(-0.476020), REAL(0.421718),
481 REAL(0.279163), REAL(-0.664604), REAL(0.417328),
482 REAL(0.277157), REAL(-0.528122), REAL(0.400208),
483 REAL(0.183069), REAL(-0.509812), REAL(0.329995),
484 REAL(0.282599), REAL(-0.429210), REAL(0.059242),
485 REAL(0.254816), REAL(-0.664541), REAL(0.290687),
486 REAL(0.271436), REAL(-0.567707), REAL(0.263966),
487 REAL(0.386561), REAL(-0.625221), REAL(-0.216870),
488 REAL(0.387086), REAL(-0.630883), REAL(-0.346073),
489 REAL(0.380021), REAL(-0.596021), REAL(-0.318679),
490 REAL(0.291269), REAL(-0.619007), REAL(-0.585707),
491 REAL(0.339280), REAL(-0.571198), REAL(-0.461946),
492 REAL(0.400045), REAL(-0.489778), REAL(-0.422640),
493 REAL(0.406817), REAL(-0.314349), REAL(-0.371230),
494 REAL(0.300588), REAL(-0.281718), REAL(-0.170549),
495 REAL(0.290866), REAL(-0.277304), REAL(-0.061905),
496 REAL(0.187735), REAL(-0.241545), REAL(0.509437),
497 REAL(0.188032), REAL(-0.287569), REAL(0.424234),
498 REAL(0.227520), REAL(-0.373262), REAL(0.293102),
499 REAL(0.266526), REAL(-0.273650), REAL(0.039597),
500 REAL(0.291592), REAL(-0.291676), REAL(0.111386),
501 REAL(0.291914), REAL(-0.122741), REAL(0.422683),
502 REAL(0.297574), REAL(-0.156119), REAL(0.373368),
503 REAL(0.286603), REAL(-0.232731), REAL(0.027162),
504 REAL(0.364663), REAL(-0.201399), REAL(0.206850),
505 REAL(0.353855), REAL(-0.132408), REAL(0.149228),
506 REAL(0.282208), REAL(-0.019715), REAL(0.314960),
507 REAL(0.331187), REAL(-0.099266), REAL(0.092701),
508 REAL(0.375463), REAL(-0.093120), REAL(-0.006467),
509 REAL(0.375917), REAL(-0.101236), REAL(-0.154882),
510 REAL(0.466635), REAL(-0.094416), REAL(-0.305669),
511 REAL(0.455805), REAL(-0.119881), REAL(-0.460632),
512 REAL(0.277465), REAL(-0.604242), REAL(-0.651871),
513 REAL(0.261022), REAL(-0.551176), REAL(-0.554667),
514 REAL(0.093627), REAL(0.258494), REAL(-0.920589),
515 REAL(0.114248), REAL(0.310608), REAL(-0.798070),
516 REAL(0.144232), REAL(0.211434), REAL(-0.835001),
517 REAL(0.119916), REAL(0.176940), REAL(-0.951159),
518 REAL(0.184061), REAL(0.101854), REAL(-0.918220),
519 REAL(0.092431), REAL(0.276521), REAL(-0.738231),
520 REAL(0.133504), REAL(0.218403), REAL(-0.758602),
521 REAL(0.194987), REAL(0.097655), REAL(-0.812476),
522 REAL(0.185542), REAL(0.011005), REAL(-0.879202),
523 REAL(0.230315), REAL(-0.127450), REAL(-0.884202),
524 REAL(0.260471), REAL(0.255056), REAL(-0.624378),
525 REAL(0.351567), REAL(-0.042194), REAL(-0.663976),
526 REAL(0.253742), REAL(0.323524), REAL(-0.433716),
527 REAL(0.411612), REAL(0.132299), REAL(-0.438264),
528 REAL(0.270513), REAL(0.356530), REAL(-0.289984),
529 REAL(0.422146), REAL(0.162819), REAL(-0.273130),
530 REAL(0.164724), REAL(0.237490), REAL(0.208912),
531 REAL(0.253806), REAL(0.092900), REAL(0.240640),
532 REAL(0.203608), REAL(0.284597), REAL(0.096223),
533 REAL(0.241006), REAL(0.343093), REAL(-0.171396),
534 REAL(0.356076), REAL(0.149288), REAL(-0.143443),
535 REAL(0.337656), REAL(0.131992), REAL(0.066374)
536};
537
538int Indices[IndexCount / 3][3] = {
539 {126,134,133},
540 {342,138,134},
541 {133,134,138},
542 {126,342,134},
543 {312,316,317},
544 {169,163,162},
545 {312,317,319},
546 {312,319,318},
547 {169,162,164},
548 {169,168,163},
549 {312,314,315},
550 {169,164,165},
551 {169,167,168},
552 {312,315,316},
553 {312,313,314},
554 {169,165,166},
555 {169,166,167},
556 {312,318,313},
557 {308,304,305},
558 {308,305,306},
559 {179,181,188},
560 {177,173,175},
561 {177,175,176},
562 {302,293,300},
563 {322,294,304},
564 {188,176,175},
565 {188,175,179},
566 {158,177,187},
567 {305,293,302},
568 {305,302,306},
569 {322,304,308},
570 {188,181,183},
571 {158,173,177},
572 {293,298,300},
573 {304,294,296},
574 {304,296,305},
575 {185,176,188},
576 {185,188,183},
577 {187,177,176},
578 {187,176,185},
579 {305,296,298},
580 {305,298,293},
581 {436,432, 28},
582 {436, 28, 23},
583 {434,278,431},
584 { 30,208,209},
585 { 30,209, 29},
586 { 19, 20, 24},
587 {208,207,211},
588 {208,211,209},
589 { 19,210,212},
590 {433,434,431},
591 {433,431,432},
592 {433,432,436},
593 {436,437,433},
594 {277,275,276},
595 {277,276,278},
596 {209,210, 25},
597 { 21, 26, 24},
598 { 21, 24, 20},
599 { 25, 26, 27},
600 { 25, 27, 29},
601 {435,439,277},
602 {439,275,277},
603 {432,431, 30},
604 {432, 30, 28},
605 {433,437,438},
606 {433,438,435},
607 {434,277,278},
608 { 24, 25,210},
609 { 24, 26, 25},
610 { 29, 27, 28},
611 { 29, 28, 30},
612 { 19, 24,210},
613 {208, 30,431},
614 {208,431,278},
615 {435,434,433},
616 {435,277,434},
617 { 25, 29,209},
618 { 27, 22, 23},
619 { 27, 23, 28},
620 { 26, 22, 27},
621 { 26, 21, 22},
622 {212,210,209},
623 {212,209,211},
624 {207,208,278},
625 {207,278,276},
626 {439,435,438},
627 { 12, 9, 10},
628 { 12, 10, 13},
629 { 2, 3, 5},
630 { 2, 5, 4},
631 { 16, 13, 14},
632 { 16, 14, 17},
633 { 22, 21, 16},
634 { 13, 10, 11},
635 { 13, 11, 14},
636 { 1, 0, 3},
637 { 1, 3, 2},
638 { 15, 12, 16},
639 { 19, 18, 15},
640 { 19, 15, 16},
641 { 19, 16, 20},
642 { 9, 1, 2},
643 { 9, 2, 10},
644 { 3, 7, 8},
645 { 3, 8, 5},
646 { 16, 17, 23},
647 { 16, 23, 22},
648 { 21, 20, 16},
649 { 10, 2, 4},
650 { 10, 4, 11},
651 { 0, 6, 7},
652 { 0, 7, 3},
653 { 12, 13, 16},
654 {451,446,445},
655 {451,445,450},
656 {442,440,439},
657 {442,439,438},
658 {442,438,441},
659 {421,420,422},
660 {412,411,426},
661 {412,426,425},
662 {408,405,407},
663 {413, 67, 68},
664 {413, 68,414},
665 {391,390,412},
666 { 80,384,386},
667 {404,406,378},
668 {390,391,377},
669 {390,377, 88},
670 {400,415,375},
671 {398,396,395},
672 {398,395,371},
673 {398,371,370},
674 {112,359,358},
675 {112,358,113},
676 {351,352,369},
677 {125,349,348},
678 {345,343,342},
679 {342,340,339},
680 {341,335,337},
681 {328,341,327},
682 {331,323,333},
683 {331,322,323},
684 {327,318,319},
685 {327,319,328},
686 {315,314,324},
687 {302,300,301},
688 {302,301,303},
689 {320,311,292},
690 {285,284,289},
691 {310,307,288},
692 {310,288,290},
693 {321,350,281},
694 {321,281,282},
695 {423,448,367},
696 {272,273,384},
697 {272,384,274},
698 {264,265,382},
699 {264,382,383},
700 {440,442,261},
701 {440,261,263},
702 {252,253,254},
703 {252,254,251},
704 {262,256,249},
705 {262,249,248},
706 {228,243,242},
707 {228, 31,243},
708 {213,215,238},
709 {213,238,237},
710 { 19,212,230},
711 {224,225,233},
712 {224,233,231},
713 {217,218, 56},
714 {217, 56, 54},
715 {217,216,239},
716 {217,239,238},
717 {217,238,215},
718 {218,217,215},
719 {218,215,214},
720 { 6,102,206},
721 {186,199,200},
722 {197,182,180},
723 {170,171,157},
724 {201,200,189},
725 {170,190,191},
726 {170,191,192},
727 {175,174,178},
728 {175,178,179},
729 {168,167,155},
730 {122,149,158},
731 {122,158,159},
732 {135,153,154},
733 {135,154,118},
734 {143,140,141},
735 {143,141,144},
736 {132,133,136},
737 {130,126,133},
738 {124,125,127},
739 {122,101,100},
740 {122,100,121},
741 {110,108,107},
742 {110,107,109},
743 { 98, 99, 97},
744 { 98, 97, 64},
745 { 98, 64, 66},
746 { 87, 55, 57},
747 { 83, 82, 79},
748 { 83, 79, 84},
749 { 78, 74, 50},
750 { 49, 71, 41},
751 { 49, 41, 37},
752 { 49, 37, 36},
753 { 58, 44, 60},
754 { 60, 59, 58},
755 { 51, 34, 33},
756 { 39, 40, 42},
757 { 39, 42, 38},
758 {243,240, 33},
759 {243, 33,229},
760 { 39, 38, 6},
761 { 44, 46, 40},
762 { 55, 56, 57},
763 { 64, 62, 65},
764 { 64, 65, 66},
765 { 41, 71, 45},
766 { 75, 50, 51},
767 { 81, 79, 82},
768 { 77, 88, 73},
769 { 93, 92, 94},
770 { 68, 47, 46},
771 { 96, 97, 99},
772 { 96, 99, 95},
773 {110,109,111},
774 {111,112,110},
775 {114,113,123},
776 {114,123,124},
777 {132,131,129},
778 {133,137,136},
779 {135,142,145},
780 {145,152,135},
781 {149,147,157},
782 {157,158,149},
783 {164,150,151},
784 {153,163,168},
785 {153,168,154},
786 {185,183,182},
787 {185,182,184},
788 {161,189,190},
789 {200,199,191},
790 {200,191,190},
791 {180,178,195},
792 {180,195,196},
793 {102,101,204},
794 {102,204,206},
795 { 43, 48,104},
796 { 43,104,103},
797 {216,217, 54},
798 {216, 54, 32},
799 {207,224,231},
800 {230,212,211},
801 {230,211,231},
802 {227,232,241},
803 {227,241,242},
804 {235,234,241},
805 {235,241,244},
806 {430,248,247},
807 {272,274,253},
808 {272,253,252},
809 {439,260,275},
810 {225,224,259},
811 {225,259,257},
812 {269,270,407},
813 {269,407,405},
814 {270,269,273},
815 {270,273,272},
816 {273,269,268},
817 {273,268,267},
818 {273,267,266},
819 {273,266,265},
820 {273,265,264},
821 {448,279,367},
822 {281,350,368},
823 {285,286,301},
824 {290,323,310},
825 {290,311,323},
826 {282,281,189},
827 {292,311,290},
828 {292,290,291},
829 {307,306,302},
830 {307,302,303},
831 {316,315,324},
832 {316,324,329},
833 {331,351,350},
834 {330,334,335},
835 {330,335,328},
836 {341,337,338},
837 {344,355,354},
838 {346,345,348},
839 {346,348,347},
840 {364,369,352},
841 {364,352,353},
842 {365,363,361},
843 {365,361,362},
844 {376,401,402},
845 {373,372,397},
846 {373,397,400},
847 {376, 92,377},
848 {381,378,387},
849 {381,387,385},
850 {386, 77, 80},
851 {390,389,412},
852 {416,417,401},
853 {403,417,415},
854 {408,429,430},
855 {419,423,418},
856 {427,428,444},
857 {427,444,446},
858 {437,436,441},
859 {450,445, 11},
860 {450, 11, 4},
861 {447,449, 5},
862 {447, 5, 8},
863 {441,438,437},
864 {425,426,451},
865 {425,451,452},
866 {417,421,415},
867 {408,407,429},
868 {399,403,400},
869 {399,400,397},
870 {394,393,416},
871 {389,411,412},
872 {386,383,385},
873 {408,387,378},
874 {408,378,406},
875 {377,391,376},
876 { 94,375,415},
877 {372,373,374},
878 {372,374,370},
879 {359,111,360},
880 {359,112,111},
881 {113,358,349},
882 {113,349,123},
883 {346,343,345},
884 {343,340,342},
885 {338,336,144},
886 {338,144,141},
887 {327,341,354},
888 {327,354,326},
889 {331,350,321},
890 {331,321,322},
891 {314,313,326},
892 {314,326,325},
893 {300,298,299},
894 {300,299,301},
895 {288,287,289},
896 {189,292,282},
897 {287,288,303},
898 {284,285,297},
899 {368,280,281},
900 {448,447,279},
901 {274,226,255},
902 {267,268,404},
903 {267,404,379},
904 {429,262,430},
905 {439,440,260},
906 {257,258,249},
907 {257,249,246},
908 {430,262,248},
909 {234,228,242},
910 {234,242,241},
911 {237,238,239},
912 {237,239,236},
913 { 15, 18,227},
914 { 15,227,229},
915 {222,223, 82},
916 {222, 82, 83},
917 {214,215,213},
918 {214,213, 81},
919 { 38,102, 6},
920 {122,159,200},
921 {122,200,201},
922 {174,171,192},
923 {174,192,194},
924 {197,193,198},
925 {190,170,161},
926 {181,179,178},
927 {181,178,180},
928 {166,156,155},
929 {163,153,152},
930 {163,152,162},
931 {120,156,149},
932 {120,149,121},
933 {152,153,135},
934 {140,143,142},
935 {135,131,132},
936 {135,132,136},
937 {130,129,128},
938 {130,128,127},
939 {100,105,119},
940 {100,119,120},
941 {106,104,107},
942 {106,107,108},
943 { 91, 95, 59},
944 { 93, 94, 68},
945 { 91, 89, 92},
946 { 76, 53, 55},
947 { 76, 55, 87},
948 { 81, 78, 79},
949 { 74, 73, 49},
950 { 69, 60, 45},
951 { 58, 62, 64},
952 { 58, 64, 61},
953 { 53, 31, 32},
954 { 32, 54, 53},
955 { 42, 43, 38},
956 { 35, 36, 0},
957 { 35, 0, 1},
958 { 34, 35, 1},
959 { 34, 1, 9},
960 { 44, 40, 41},
961 { 44, 41, 45},
962 { 33,240, 51},
963 { 63, 62, 58},
964 { 63, 58, 59},
965 { 45, 71, 70},
966 { 76, 75, 51},
967 { 76, 51, 52},
968 { 86, 85, 84},
969 { 86, 84, 87},
970 { 89, 72, 73},
971 { 89, 73, 88},
972 { 91, 92, 96},
973 { 91, 96, 95},
974 { 72, 91, 60},
975 { 72, 60, 69},
976 {104,106,105},
977 {119,105,117},
978 {119,117,118},
979 {124,127,128},
980 {117,116,129},
981 {117,129,131},
982 {118,117,131},
983 {135,140,142},
984 {146,150,152},
985 {146,152,145},
986 {149,122,121},
987 {166,165,151},
988 {166,151,156},
989 {158,172,173},
990 {161,160,189},
991 {199,198,193},
992 {199,193,191},
993 {204,201,202},
994 {178,174,194},
995 {200,159,186},
996 {109, 48, 67},
997 { 48,107,104},
998 {216, 32,236},
999 {216,236,239},
1000 {223,214, 81},
1001 {223, 81, 82},
1002 { 33, 12, 15},
1003 { 32,228,234},
1004 { 32,234,236},
1005 {240, 31, 52},
1006 {256,255,246},
1007 {256,246,249},
1008 {258,263,248},
1009 {258,248,249},
1010 {275,260,259},
1011 {275,259,276},
1012 {207,276,259},
1013 {270,271,429},
1014 {270,429,407},
1015 {413,418,366},
1016 {413,366,365},
1017 {368,367,279},
1018 {368,279,280},
1019 {303,301,286},
1020 {303,286,287},
1021 {283,282,292},
1022 {283,292,291},
1023 {320,292,189},
1024 {298,296,297},
1025 {298,297,299},
1026 {318,327,326},
1027 {318,326,313},
1028 {329,330,317},
1029 {336,333,320},
1030 {326,354,353},
1031 {334,332,333},
1032 {334,333,336},
1033 {342,339,139},
1034 {342,139,138},
1035 {345,342,126},
1036 {347,357,356},
1037 {369,368,351},
1038 {363,356,357},
1039 {363,357,361},
1040 {366,367,368},
1041 {366,368,369},
1042 {375,373,400},
1043 { 92, 90,377},
1044 {409,387,408},
1045 {386,385,387},
1046 {386,387,388},
1047 {412,394,391},
1048 {396,398,399},
1049 {408,406,405},
1050 {415,421,419},
1051 {415,419,414},
1052 {425,452,448},
1053 {425,448,424},
1054 {444,441,443},
1055 {448,452,449},
1056 {448,449,447},
1057 {446,444,443},
1058 {446,443,445},
1059 {250,247,261},
1060 {250,261,428},
1061 {421,422,423},
1062 {421,423,419},
1063 {427,410,250},
1064 {417,403,401},
1065 {403,402,401},
1066 {420,392,412},
1067 {420,412,425},
1068 {420,425,424},
1069 {386,411,389},
1070 {383,382,381},
1071 {383,381,385},
1072 {378,379,404},
1073 {372,371,395},
1074 {372,395,397},
1075 {371,372,370},
1076 {361,359,360},
1077 {361,360,362},
1078 {368,350,351},
1079 {349,347,348},
1080 {356,355,344},
1081 {356,344,346},
1082 {344,341,340},
1083 {344,340,343},
1084 {338,337,336},
1085 {328,335,341},
1086 {324,352,351},
1087 {324,351,331},
1088 {320,144,336},
1089 {314,325,324},
1090 {322,308,309},
1091 {310,309,307},
1092 {287,286,289},
1093 {203,280,279},
1094 {203,279,205},
1095 {297,295,283},
1096 {297,283,284},
1097 {447,205,279},
1098 {274,384, 80},
1099 {274, 80,226},
1100 {266,267,379},
1101 {266,379,380},
1102 {225,257,246},
1103 {225,246,245},
1104 {256,254,253},
1105 {256,253,255},
1106 {430,247,250},
1107 {226,235,244},
1108 {226,244,245},
1109 {232,233,244},
1110 {232,244,241},
1111 {230, 18, 19},
1112 { 32, 31,228},
1113 {219,220, 86},
1114 {219, 86, 57},
1115 {226,213,235},
1116 {206, 7, 6},
1117 {122,201,101},
1118 {201,204,101},
1119 {180,196,197},
1120 {170,192,171},
1121 {200,190,189},
1122 {194,193,195},
1123 {183,181,180},
1124 {183,180,182},
1125 {155,154,168},
1126 {149,156,151},
1127 {149,151,148},
1128 {155,156,120},
1129 {145,142,143},
1130 {145,143,146},
1131 {136,137,140},
1132 {133,132,130},
1133 {128,129,116},
1134 {100,120,121},
1135 {110,112,113},
1136 {110,113,114},
1137 { 66, 65, 63},
1138 { 66, 63, 99},
1139 { 66, 99, 98},
1140 { 96, 46, 61},
1141 { 89, 88, 90},
1142 { 86, 87, 57},
1143 { 80, 78, 81},
1144 { 72, 69, 49},
1145 { 67, 48, 47},
1146 { 67, 47, 68},
1147 { 56, 55, 53},
1148 { 50, 49, 36},
1149 { 50, 36, 35},
1150 { 40, 39, 41},
1151 {242,243,229},
1152 {242,229,227},
1153 { 6, 37, 39},
1154 { 42, 47, 48},
1155 { 42, 48, 43},
1156 { 61, 46, 44},
1157 { 45, 70, 69},
1158 { 69, 70, 71},
1159 { 69, 71, 49},
1160 { 74, 78, 77},
1161 { 83, 84, 85},
1162 { 73, 74, 77},
1163 { 93, 96, 92},
1164 { 68, 46, 93},
1165 { 95, 99, 63},
1166 { 95, 63, 59},
1167 {115,108,110},
1168 {115,110,114},
1169 {125,126,127},
1170 {129,130,132},
1171 {137,133,138},
1172 {137,138,139},
1173 {148,146,143},
1174 {148,143,147},
1175 {119,118,154},
1176 {161,147,143},
1177 {165,164,151},
1178 {158,157,171},
1179 {158,171,172},
1180 {159,158,187},
1181 {159,187,186},
1182 {194,192,191},
1183 {194,191,193},
1184 {189,202,201},
1185 {182,197,184},
1186 {205, 8, 7},
1187 { 48,109,107},
1188 {218,219, 57},
1189 {218, 57, 56},
1190 {207,231,211},
1191 {232,230,231},
1192 {232,231,233},
1193 { 53, 52, 31},
1194 {388,411,386},
1195 {409,430,250},
1196 {262,429,254},
1197 {262,254,256},
1198 {442,444,428},
1199 {273,264,383},
1200 {273,383,384},
1201 {429,271,251},
1202 {429,251,254},
1203 {413,365,362},
1204 { 67,413,360},
1205 {282,283,295},
1206 {285,301,299},
1207 {202,281,280},
1208 {284,283,291},
1209 {284,291,289},
1210 {320,189,160},
1211 {308,306,307},
1212 {307,309,308},
1213 {319,317,330},
1214 {319,330,328},
1215 {353,352,324},
1216 {332,331,333},
1217 {340,341,338},
1218 {354,341,344},
1219 {349,358,357},
1220 {349,357,347},
1221 {364,355,356},
1222 {364,356,363},
1223 {364,365,366},
1224 {364,366,369},
1225 {374,376,402},
1226 {375, 92,373},
1227 { 77,389,390},
1228 {382,380,381},
1229 {389, 77,386},
1230 {393,394,412},
1231 {393,412,392},
1232 {401,394,416},
1233 {415,400,403},
1234 {411,410,427},
1235 {411,427,426},
1236 {422,420,424},
1237 {247,248,263},
1238 {247,263,261},
1239 {445,443, 14},
1240 {445, 14, 11},
1241 {449,450, 4},
1242 {449, 4, 5},
1243 {443,441, 17},
1244 {443, 17, 14},
1245 {436, 23, 17},
1246 {436, 17,441},
1247 {424,448,422},
1248 {448,423,422},
1249 {414,419,418},
1250 {414,418,413},
1251 {406,404,405},
1252 {399,397,395},
1253 {399,395,396},
1254 {420,416,392},
1255 {388,410,411},
1256 {386,384,383},
1257 {390, 88, 77},
1258 {375, 94, 92},
1259 {415,414, 68},
1260 {415, 68, 94},
1261 {370,374,402},
1262 {370,402,398},
1263 {361,357,358},
1264 {361,358,359},
1265 {125,348,126},
1266 {346,344,343},
1267 {340,338,339},
1268 {337,335,334},
1269 {337,334,336},
1270 {325,353,324},
1271 {324,331,332},
1272 {324,332,329},
1273 {323,322,309},
1274 {323,309,310},
1275 {294,295,297},
1276 {294,297,296},
1277 {289,286,285},
1278 {202,280,203},
1279 {288,307,303},
1280 {282,295,321},
1281 { 67,360,111},
1282 {418,423,367},
1283 {418,367,366},
1284 {272,252,251},
1285 {272,251,271},
1286 {272,271,270},
1287 {255,253,274},
1288 {265,266,380},
1289 {265,380,382},
1290 {442,428,261},
1291 {440,263,258},
1292 {440,258,260},
1293 {409,250,410},
1294 {255,226,245},
1295 {255,245,246},
1296 { 31,240,243},
1297 {236,234,235},
1298 {236,235,237},
1299 {233,225,245},
1300 {233,245,244},
1301 {220,221, 85},
1302 {220, 85, 86},
1303 { 81,213,226},
1304 { 81,226, 80},
1305 { 7,206,205},
1306 {186,184,198},
1307 {186,198,199},
1308 {204,203,205},
1309 {204,205,206},
1310 {195,193,196},
1311 {171,174,172},
1312 {173,174,175},
1313 {173,172,174},
1314 {155,167,166},
1315 {160,161,143},
1316 {160,143,144},
1317 {119,154,155},
1318 {148,151,150},
1319 {148,150,146},
1320 {140,137,139},
1321 {140,139,141},
1322 {127,126,130},
1323 {114,124,128},
1324 {114,128,115},
1325 {117,105,106},
1326 {117,106,116},
1327 {104,105,100},
1328 {104,100,103},
1329 { 59, 60, 91},
1330 { 97, 96, 61},
1331 { 97, 61, 64},
1332 { 91, 72, 89},
1333 { 87, 84, 79},
1334 { 87, 79, 76},
1335 { 78, 80, 77},
1336 { 49, 50, 74},
1337 { 60, 44, 45},
1338 { 61, 44, 58},
1339 { 51, 50, 35},
1340 { 51, 35, 34},
1341 { 39, 37, 41},
1342 { 33, 34, 9},
1343 { 33, 9, 12},
1344 { 0, 36, 37},
1345 { 0, 37, 6},
1346 { 40, 46, 47},
1347 { 40, 47, 42},
1348 { 53, 54, 56},
1349 { 65, 62, 63},
1350 { 72, 49, 73},
1351 { 79, 78, 75},
1352 { 79, 75, 76},
1353 { 52, 53, 76},
1354 { 92, 89, 90},
1355 { 96, 93, 46},
1356 {102,103,100},
1357 {102,100,101},
1358 {116,106,108},
1359 {116,108,115},
1360 {123,125,124},
1361 {116,115,128},
1362 {118,131,135},
1363 {140,135,136},
1364 {148,147,149},
1365 {120,119,155},
1366 {164,162,152},
1367 {164,152,150},
1368 {157,147,161},
1369 {157,161,170},
1370 {186,187,185},
1371 {186,185,184},
1372 {193,197,196},
1373 {202,203,204},
1374 {194,195,178},
1375 {198,184,197},
1376 { 67,111,109},
1377 { 38, 43,103},
1378 { 38,103,102},
1379 {214,223,222},
1380 {214,222,221},
1381 {214,221,220},
1382 {214,220,219},
1383 {214,219,218},
1384 {213,237,235},
1385 {221,222, 83},
1386 {221, 83, 85},
1387 { 15,229, 33},
1388 {227, 18,230},
1389 {227,230,232},
1390 { 52, 51,240},
1391 { 75, 78, 50},
1392 {408,430,409},
1393 {260,258,257},
1394 {260,257,259},
1395 {224,207,259},
1396 {268,269,405},
1397 {268,405,404},
1398 {413,362,360},
1399 {447, 8,205},
1400 {299,297,285},
1401 {189,281,202},
1402 {290,288,289},
1403 {290,289,291},
1404 {322,321,295},
1405 {322,295,294},
1406 {333,323,311},
1407 {333,311,320},
1408 {317,316,329},
1409 {320,160,144},
1410 {353,325,326},
1411 {329,332,334},
1412 {329,334,330},
1413 {339,338,141},
1414 {339,141,139},
1415 {348,345,126},
1416 {347,356,346},
1417 {123,349,125},
1418 {364,353,354},
1419 {364,354,355},
1420 {365,364,363},
1421 {376,391,394},
1422 {376,394,401},
1423 { 92,376,374},
1424 { 92,374,373},
1425 {377, 90, 88},
1426 {380,379,378},
1427 {380,378,381},
1428 {388,387,409},
1429 {388,409,410},
1430 {416,393,392},
1431 {399,398,402},
1432 {399,402,403},
1433 {250,428,427},
1434 {421,417,416},
1435 {421,416,420},
1436 {426,427,446},
1437 {426,446,451},
1438 {444,442,441},
1439 {452,451,450},
1440 {452,450,449}
1441};
1442
1443
1444// this is called by dSpaceCollide when two objects in space are
1445// potentially colliding.
1446
1447static void nearCallback (void *data, dGeomID o1, dGeomID o2)
1448{
1449 int i;
1450 // if (o1->body && o2->body) return;
1451
1452 // exit without doing anything if the two bodies are connected by a joint
1453 dBodyID b1 = dGeomGetBody(o1);
1454 dBodyID b2 = dGeomGetBody(o2);
1455 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
1456
1457 dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
1458 for (i=0; i<MAX_CONTACTS; i++) {
1459 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
1460 contact[i].surface.mu = dInfinity;
1461 contact[i].surface.mu2 = 0;
1462 contact[i].surface.bounce = 0.1;
1463 contact[i].surface.bounce_vel = 0.1;
1464 contact[i].surface.soft_cfm = 0.01;
1465 }
1466 if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
1467 sizeof(dContact))) {
1468 dMatrix3 RI;
1469 dRSetIdentity (RI);
1470 const dReal ss[3] = {0.02,0.02,0.02};
1471 for (i=0; i<numc; i++) {
1472 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
1473 dJointAttach (c,b1,b2);
1474 if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
1475 }
1476 }
1477}
1478
1479
1480// start simulation - set viewpoint
1481
1482static void start()
1483{
1484 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
1485 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
1486 dsSetViewpoint (xyz,hpr);
1487 printf ("To drop another object, press:\n");
1488 printf (" b for box.\n");
1489 printf (" s for sphere.\n");
1490 printf (" y for cylinder.\n");
1491 printf (" c for capsule.\n");
1492 printf (" x for a composite object.\n");
1493 printf (" m for a trimesh.\n");
1494 printf ("To select an object, press space.\n");
1495 printf ("To disable the selected object, press d.\n");
1496 printf ("To enable the selected object, press e.\n");
1497 printf ("To toggle showing the geom AABBs, press a.\n");
1498 printf ("To toggle showing the contact points, press t.\n");
1499 printf ("To toggle dropping from random position/orientation, press r.\n");
1500}
1501
1502
1503char locase (char c)
1504{
1505 if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
1506 else return c;
1507}
1508
1509
1510// called when a key pressed
1511
1512static void command (int cmd)
1513{
1514 int i,j,k;
1515 dReal sides[3];
1516 dMass m;
1517
1518 cmd = locase (cmd);
1519 if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'm' || cmd == 'y' ) {
1520 if (num < NUM) {
1521 i = num;
1522 num++;
1523 }
1524 else {
1525 i = nextobj;
1526 nextobj++;
1527 if (nextobj >= num) nextobj = 0;
1528
1529 // destroy the body and geoms for slot i
1530 dBodyDestroy (obj[i].body);
1531 for (k=0; k < GPB; k++) {
1532 if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
1533 }
1534 memset (&obj[i],0,sizeof(obj[i]));
1535 }
1536
1537 obj[i].body = dBodyCreate (world);
1538 for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
1539
1540 dMatrix3 R;
1541 if (random_pos) {
1542 dBodySetPosition (obj[i].body,
1543 dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3);
1544 dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1545 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1546 }
1547 else {
1548 dReal maxheight = 0;
1549 for (k=0; k<num; k++) {
1550 const dReal *pos = dBodyGetPosition (obj[k].body);
1551 if (pos[2] > maxheight) maxheight = pos[2];
1552 }
1553 dBodySetPosition (obj[i].body, 0,0,maxheight+1);
1554 dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
1555 }
1556 dBodySetRotation (obj[i].body,R);
1557 dBodySetData (obj[i].body,(void*)(size_t)i);
1558
1559 if (cmd == 'b') {
1560 dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
1561 obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
1562 }
1563 else if (cmd == 'c') {
1564 sides[0] *= 0.5;
1565 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
1566 obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
1567 }
1568 else if (cmd == 'y') {
1569 sides[1] *= 0.5;
1570 dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
1571 obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
1572 }
1573 else if (cmd == 's') {
1574 sides[0] *= 0.5;
1575 dMassSetSphere (&m,DENSITY,sides[0]);
1576 obj[i].geom[0] = dCreateSphere (space,sides[0]);
1577 }
1578 else if (cmd == 'm') {
1579 dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
1580 dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
1581
1582 obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0);
1583
1584 // remember the mesh's dTriMeshDataID on its userdata for convenience.
1585 dGeomSetData(obj[i].geom[0], new_tmdata);
1586
1587 dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] );
1588 printf("mass at %f %f %f\n", m.c[0], m.c[1], m.c[2]);
1589 dGeomSetPosition(obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2]);
1590 dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
1591 }
1592 else if (cmd == 'x') {
1593 dGeomID g2[GPB]; // encapsulated geometries
1594 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
1595
1596 // start accumulating masses for the encapsulated geometries
1597 dMass m2;
1598 dMassSetZero (&m);
1599
1600 // set random delta positions
1601 for (j=0; j<GPB; j++) {
1602 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
1603 }
1604
1605 for (k=0; k<GPB; k++) {
1606 obj[i].geom[k] = dCreateGeomTransform (space);
1607 dGeomTransformSetCleanup (obj[i].geom[k],1);
1608 if (k==0) {
1609 dReal radius = dRandReal()*0.25+0.05;
1610 g2[k] = dCreateSphere (0,radius);
1611 dMassSetSphere (&m2,DENSITY,radius);
1612 }
1613 else if (k==1) {
1614 g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
1615 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
1616 }
1617 else {
1618 dReal radius = dRandReal()*0.1+0.05;
1619 dReal length = dRandReal()*1.0+0.1;
1620 g2[k] = dCreateCapsule (0,radius,length);
1621 dMassSetCapsule (&m2,DENSITY,3,radius,length);
1622 }
1623 dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
1624
1625 // set the transformation (adjust the mass too)
1626 dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
1627 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
1628 dMatrix3 Rtx;
1629 dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
1630 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
1631 dGeomSetRotation (g2[k],Rtx);
1632 dMassRotate (&m2,Rtx);
1633
1634 // add to the total mass
1635 dMassAdd (&m,&m2);
1636 }
1637
1638 // move all encapsulated objects so that the center of mass is (0,0,0)
1639 for (k=0; k<2; k++) {
1640 dGeomSetPosition (g2[k],
1641 dpos[k][0]-m.c[0],
1642 dpos[k][1]-m.c[1],
1643 dpos[k][2]-m.c[2]);
1644 }
1645 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
1646 }
1647
1648 for (k=0; k < GPB; k++) {
1649 if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
1650 }
1651
1652 dBodySetMass (obj[i].body,&m);
1653 }
1654
1655 if (cmd == ' ') {
1656 selected++;
1657 if (selected >= num) selected = 0;
1658 if (selected < 0) selected = 0;
1659 }
1660 else if (cmd == 'd' && selected >= 0 && selected < num) {
1661 dBodyDisable (obj[selected].body);
1662 }
1663 else if (cmd == 'e' && selected >= 0 && selected < num) {
1664 dBodyEnable (obj[selected].body);
1665 }
1666 else if (cmd == 'a') {
1667 show_aabb ^= 1;
1668 }
1669 else if (cmd == 't') {
1670 show_contacts ^= 1;
1671 }
1672 else if (cmd == 'r') {
1673 random_pos ^= 1;
1674 }
1675}
1676
1677
1678// draw a geom
1679
1680void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
1681{
1682 if (!g) return;
1683 if (!pos) pos = dGeomGetPosition (g);
1684 if (!R) R = dGeomGetRotation (g);
1685
1686 int type = dGeomGetClass (g);
1687 if (type == dBoxClass) {
1688 dVector3 sides;
1689 dGeomBoxGetLengths (g,sides);
1690 dsDrawBox (pos,R,sides);
1691 }
1692 else if (type == dSphereClass) {
1693 dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
1694 }
1695 else if (type == dCapsuleClass) {
1696 dReal radius,length;
1697 dGeomCapsuleGetParams (g,&radius,&length);
1698 dsDrawCapsule (pos,R,length,radius);
1699 }
1700 else if (type == dCylinderClass) {
1701 dReal radius,length;
1702 dGeomCylinderGetParams (g,&radius,&length);
1703 dsDrawCylinder (pos,R,length,radius);
1704 }
1705
1706 else if (type == dGeomTransformClass) {
1707 dGeomID g2 = dGeomTransformGetGeom (g);
1708 const dReal *pos2 = dGeomGetPosition (g2);
1709 const dReal *R2 = dGeomGetRotation (g2);
1710 dVector3 actual_pos;
1711 dMatrix3 actual_R;
1712 dMULTIPLY0_331 (actual_pos,R,pos2);
1713 actual_pos[0] += pos[0];
1714 actual_pos[1] += pos[1];
1715 actual_pos[2] += pos[2];
1716 dMULTIPLY0_333 (actual_R,R,R2);
1717 drawGeom (g2,actual_pos,actual_R,0);
1718 }
1719
1720 if (show_aabb) {
1721 // draw the bounding box for this geom
1722 dReal aabb[6];
1723 dGeomGetAABB (g,aabb);
1724 dVector3 bbpos;
1725 for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
1726 dVector3 bbsides;
1727 for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
1728 dMatrix3 RI;
1729 dRSetIdentity (RI);
1730 dsSetColorAlpha (1,0,0,0.5);
1731 dsDrawBox (bbpos,RI,bbsides);
1732 }
1733}
1734
1735
1736// set previous transformation matrix for trimesh
1737void setCurrentTransform(dGeomID geom)
1738{
1739 const dReal* Pos = dGeomGetPosition(geom);
1740 const dReal* Rot = dGeomGetRotation(geom);
1741
1742 const dReal Transform[16] =
1743 {
1744 Rot[0], Rot[4], Rot[8], 0,
1745 Rot[1], Rot[5], Rot[9], 0,
1746 Rot[2], Rot[6], Rot[10], 0,
1747 Pos[0], Pos[1], Pos[2], 1
1748 };
1749
1750 dGeomTriMeshSetLastTransform( geom, *(dMatrix4*)(&Transform) );
1751
1752}
1753
1754
1755// simulation loop
1756
1757static void simLoop (int pause)
1758{
1759 dsSetColor (0,0,2);
1760 dSpaceCollide (space,0,&nearCallback);
1761
1762
1763#if 0
1764 // What is this for??? - Bram
1765 if (!pause)
1766 {
1767 for (int i=0; i<num; i++)
1768 for (int j=0; j < GPB; j++)
1769 if (obj[i].geom[j])
1770 if (dGeomGetClass(obj[i].geom[j]) == dTriMeshClass)
1771 setCurrentTransform(obj[i].geom[j]);
1772
1773 setCurrentTransform(TriMesh1);
1774 setCurrentTransform(TriMesh2);
1775 }
1776#endif
1777
1778 //if (!pause) dWorldStep (world,0.05);
1779 if (!pause) dWorldStepFast1 (world,0.05, 5);
1780
1781 for (int j = 0; j < dSpaceGetNumGeoms(space); j++){
1782 dSpaceGetGeom(space, j);
1783 }
1784
1785 // remove all contact joints
1786 dJointGroupEmpty (contactgroup);
1787
1788 dsSetColor (1,1,0);
1789 dsSetTexture (DS_WOOD);
1790 for (int i=0; i<num; i++) {
1791 for (int j=0; j < GPB; j++) {
1792 if (obj[i].geom[j]) {
1793 if (i==selected) {
1794 dsSetColor (0,0.7,1);
1795 }
1796 else if (! dBodyIsEnabled (obj[i].body)) {
1797 dsSetColor (1,0,0);
1798 }
1799 else {
1800 dsSetColor (1,1,0);
1801 }
1802
1803 if (dGeomGetClass(obj[i].geom[j]) == dTriMeshClass) {
1804 int* Indices = (int*)::Indices;
1805
1806 // assume all trimeshes are drawn as bunnies
1807 const dReal* Pos = dGeomGetPosition(obj[i].geom[j]);
1808 const dReal* Rot = dGeomGetRotation(obj[i].geom[j]);
1809
1810 for (int ii = 0; ii < IndexCount / 3; ii++) {
1811 const dReal v[9] = { // explicit conversion from float to dReal
1812 Vertices[Indices[ii * 3 + 0] * 3 + 0],
1813 Vertices[Indices[ii * 3 + 0] * 3 + 1],
1814 Vertices[Indices[ii * 3 + 0] * 3 + 2],
1815 Vertices[Indices[ii * 3 + 1] * 3 + 0],
1816 Vertices[Indices[ii * 3 + 1] * 3 + 1],
1817 Vertices[Indices[ii * 3 + 1] * 3 + 2],
1818 Vertices[Indices[ii * 3 + 2] * 3 + 0],
1819 Vertices[Indices[ii * 3 + 2] * 3 + 1],
1820 Vertices[Indices[ii * 3 + 2] * 3 + 2]
1821 };
1822 dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
1823 }
1824
1825 // tell the tri-tri collider the current transform of the trimesh --
1826 // this is fairly important for good results.
1827
1828 // Fill in the (4x4) matrix.
1829 dReal* p_matrix = obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 );
1830
1831 p_matrix[ 0 ] = Rot[ 0 ]; p_matrix[ 1 ] = Rot[ 1 ]; p_matrix[ 2 ] = Rot[ 2 ]; p_matrix[ 3 ] = 0;
1832 p_matrix[ 4 ] = Rot[ 4 ]; p_matrix[ 5 ] = Rot[ 5 ]; p_matrix[ 6 ] = Rot[ 6 ]; p_matrix[ 7 ] = 0;
1833 p_matrix[ 8 ] = Rot[ 8 ]; p_matrix[ 9 ] = Rot[ 9 ]; p_matrix[10 ] = Rot[10 ]; p_matrix[11 ] = 0;
1834 p_matrix[12 ] = Pos[ 0 ]; p_matrix[13 ] = Pos[ 1 ]; p_matrix[14 ] = Pos[ 2 ]; p_matrix[15 ] = 1;
1835
1836 // Flip to other matrix.
1837 obj[i].last_matrix_index = !obj[i].last_matrix_index;
1838
1839 dGeomTriMeshSetLastTransform( obj[i].geom[j],
1840 *(dMatrix4*)( obj[i].matrix_dblbuff + obj[i].last_matrix_index * 16 ) );
1841
1842 } else {
1843 drawGeom (obj[i].geom[j],0,0,show_aabb);
1844 }
1845 }
1846 }
1847 }
1848
1849 int* Indices = (int*)::Indices;
1850
1851 {const dReal* Pos = dGeomGetPosition(TriMesh1);
1852 const dReal* Rot = dGeomGetRotation(TriMesh1);
1853
1854 {for (int i = 0; i < IndexCount / 3; i++){
1855 const dReal v[9] = { // explicit conversion from float to dReal
1856 Vertices[Indices[i * 3 + 0] * 3 + 0],
1857 Vertices[Indices[i * 3 + 0] * 3 + 1],
1858 Vertices[Indices[i * 3 + 0] * 3 + 2],
1859 Vertices[Indices[i * 3 + 1] * 3 + 0],
1860 Vertices[Indices[i * 3 + 1] * 3 + 1],
1861 Vertices[Indices[i * 3 + 1] * 3 + 2],
1862 Vertices[Indices[i * 3 + 2] * 3 + 0],
1863 Vertices[Indices[i * 3 + 2] * 3 + 1],
1864 Vertices[Indices[i * 3 + 2] * 3 + 2]
1865 };
1866 dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 0);
1867 }}}
1868
1869 {const dReal* Pos = dGeomGetPosition(TriMesh2);
1870 const dReal* Rot = dGeomGetRotation(TriMesh2);
1871
1872 {for (int i = 0; i < IndexCount / 3; i++){
1873 const dReal v[9] = { // explicit conversion from float to dReal
1874 Vertices[Indices[i * 3 + 0] * 3 + 0],
1875 Vertices[Indices[i * 3 + 0] * 3 + 1],
1876 Vertices[Indices[i * 3 + 0] * 3 + 2],
1877 Vertices[Indices[i * 3 + 1] * 3 + 0],
1878 Vertices[Indices[i * 3 + 1] * 3 + 1],
1879 Vertices[Indices[i * 3 + 1] * 3 + 2],
1880 Vertices[Indices[i * 3 + 2] * 3 + 0],
1881 Vertices[Indices[i * 3 + 2] * 3 + 1],
1882 Vertices[Indices[i * 3 + 2] * 3 + 2]
1883 };
1884 dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
1885 }}}
1886}
1887
1888
1889int main (int argc, char **argv)
1890{
1891 // setup pointers to drawstuff callback functions
1892 dsFunctions fn;
1893 fn.version = DS_VERSION;
1894 fn.start = &start;
1895 fn.step = &simLoop;
1896 fn.command = &command;
1897 fn.stop = 0;
1898 fn.path_to_textures = "../../drawstuff/textures";
1899 if(argc==2)
1900 {
1901 fn.path_to_textures = argv[1];
1902 }
1903
1904 // create world
1905 dInitODE();
1906 world = dWorldCreate();
1907
1908 space = dSimpleSpaceCreate(0);
1909 contactgroup = dJointGroupCreate (0);
1910 dWorldSetGravity (world,0,0,-0.5);
1911 dWorldSetCFM (world,1e-5);
1912 dCreatePlane (space,0,0,1,0);
1913 memset (obj,0,sizeof(obj));
1914
1915 // note: can't share tridata if intending to trimesh-trimesh collide
1916 TriData1 = dGeomTriMeshDataCreate();
1917 dGeomTriMeshDataBuildSingle(TriData1, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
1918 TriData2 = dGeomTriMeshDataCreate();
1919 dGeomTriMeshDataBuildSingle(TriData2, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
1920
1921 TriMesh1 = dCreateTriMesh(space, TriData1, 0, 0, 0);
1922 TriMesh2 = dCreateTriMesh(space, TriData2, 0, 0, 0);
1923 dGeomSetData(TriMesh1, TriData1);
1924 dGeomSetData(TriMesh2, TriData2);
1925
1926 {dGeomSetPosition(TriMesh1, 0, 0, 0.9);
1927 dMatrix3 Rotation;
1928 dRFromAxisAndAngle(Rotation, 1, 0, 0, M_PI / 2);
1929 dGeomSetRotation(TriMesh1, Rotation);}
1930
1931 {dGeomSetPosition(TriMesh2, 1, 0, 0.9);
1932 dMatrix3 Rotation;
1933 dRFromAxisAndAngle(Rotation, 1, 0, 0, M_PI / 2);
1934 dGeomSetRotation(TriMesh2, Rotation);}
1935
1936 // run simulation
1937 dsSimulationLoop (argc,argv,352,288,&fn);
1938
1939 dJointGroupDestroy (contactgroup);
1940 dSpaceDestroy (space);
1941 dWorldDestroy (world);
1942 dCloseODE();
1943 return 0;
1944}
diff --git a/libraries/ode-0.9/ode/demo/demo_ode.cpp b/libraries/ode-0.9/ode/demo/demo_ode.cpp
deleted file mode 100644
index bd22ac1..0000000
--- a/libraries/ode-0.9/ode/demo/demo_ode.cpp
+++ /dev/null
@@ -1,1128 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <setjmp.h>
24#include <ode/ode.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30//****************************************************************************
31// matrix accessors
32
33#define _A(i,j) A[(i)*4+(j)]
34#define _I(i,j) I[(i)*4+(j)]
35#define _R(i,j) R[(i)*4+(j)]
36
37//****************************************************************************
38// tolerances
39
40#ifdef dDOUBLE
41const double tol = 1e-10;
42#endif
43
44#ifdef dSINGLE
45const double tol = 1e-5;
46#endif
47
48//****************************************************************************
49// misc messages and error handling
50
51#ifdef __GNUC__
52#define HEADER printf ("%s()\n", __FUNCTION__);
53#else
54#define HEADER printf ("%s:%d\n",__FILE__,__LINE__);
55#endif
56
57static jmp_buf jump_buffer;
58
59
60void myMessageFunction (int num, const char *msg, va_list ap)
61{
62 printf ("(Message %d: ",num);
63 vprintf (msg,ap);
64 printf (")");
65 dSetMessageHandler (0);
66 longjmp (jump_buffer,1);
67}
68
69
70#define TRAP_MESSAGE(do,ifnomsg,ifmsg) \
71 dSetMessageHandler (&myMessageFunction); \
72 if (setjmp (jump_buffer)) { \
73 dSetMessageHandler (0); \
74 ifmsg ; \
75 } \
76 else { \
77 dSetMessageHandler (&myMessageFunction); \
78 do ; \
79 ifnomsg ; \
80 } \
81 dSetMessageHandler (0);
82
83//****************************************************************************
84// utility stuff
85
86// compare two numbers, within a threshhold, return 1 if approx equal
87
88int cmp (dReal a, dReal b)
89{
90 return (fabs(a-b) < tol);
91}
92
93//****************************************************************************
94// matrix utility stuff
95
96// compare a 3x3 matrix with the identity
97
98int cmpIdentityMat3 (dMatrix3 A)
99{
100 return
101 (cmp(_A(0,0),1.0) && cmp(_A(0,1),0.0) && cmp(_A(0,2),0.0) &&
102 cmp(_A(1,0),0.0) && cmp(_A(1,1),1.0) && cmp(_A(1,2),0.0) &&
103 cmp(_A(2,0),0.0) && cmp(_A(2,1),0.0) && cmp(_A(2,2),1.0));
104}
105
106
107// transpose a 3x3 matrix in-line
108
109void transpose3x3 (dMatrix3 A)
110{
111 dReal tmp;
112 tmp=A[4]; A[4]=A[1]; A[1]=tmp;
113 tmp=A[8]; A[8]=A[2]; A[2]=tmp;
114 tmp=A[9]; A[9]=A[6]; A[6]=tmp;
115}
116
117//****************************************************************************
118// test miscellaneous math functions
119
120void testRandomNumberGenerator()
121{
122 HEADER;
123 if (dTestRand()) printf ("\tpassed\n");
124 else printf ("\tFAILED\n");
125}
126
127
128void testInfinity()
129{
130 HEADER;
131 if (1e10 < dInfinity && -1e10 > -dInfinity && -dInfinity < dInfinity)
132 printf ("\tpassed\n");
133 else printf ("\tFAILED\n");
134}
135
136
137void testPad()
138{
139 HEADER;
140 char s[100];
141 s[0]=0;
142 for (int i=0; i<=16; i++) sprintf (s+strlen(s),"%d ",dPAD(i));
143 printf ("\t%s\n", strcmp(s,"0 1 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16 ") ?
144 "FAILED" : "passed");
145}
146
147
148void testCrossProduct()
149{
150 HEADER;
151
152 dVector3 a1,a2,b,c;
153 dMatrix3 B;
154 dMakeRandomVector (b,3,1.0);
155 dMakeRandomVector (c,3,1.0);
156
157 dCROSS (a1,=,b,c);
158
159 dSetZero (B,12);
160 dCROSSMAT (B,b,4,+,-);
161 dMultiply0 (a2,B,c,3,3,1);
162
163 dReal diff = dMaxDifference(a1,a2,3,1);
164 printf ("\t%s\n", diff > tol ? "FAILED" : "passed");
165}
166
167
168void testSetZero()
169{
170 HEADER;
171 dReal a[100];
172 dMakeRandomVector (a,100,1.0);
173 dSetZero (a,100);
174 for (int i=0; i<100; i++) if (a[i] != 0.0) {
175 printf ("\tFAILED\n");
176 return;
177 }
178 printf ("\tpassed\n");
179}
180
181
182void testNormalize3()
183{
184 HEADER;
185 int i,j,bad=0;
186 dVector3 n1,n2;
187 for (i=0; i<1000; i++) {
188 dMakeRandomVector (n1,3,1.0);
189 for (j=0; j<3; j++) n2[j]=n1[j];
190 dNormalize3 (n2);
191 if (dFabs(dDOT(n2,n2) - 1.0) > tol) bad |= 1;
192 if (dFabs(n2[0]/n1[0] - n2[1]/n1[1]) > tol) bad |= 2;
193 if (dFabs(n2[0]/n1[0] - n2[2]/n1[2]) > tol) bad |= 4;
194 if (dFabs(n2[1]/n1[1] - n2[2]/n1[2]) > tol) bad |= 8;
195 if (dFabs(dDOT(n2,n1) - dSqrt(dDOT(n1,n1))) > tol) bad |= 16;
196 if (bad) {
197 printf ("\tFAILED (code=%x)\n",bad);
198 return;
199 }
200 }
201 printf ("\tpassed\n");
202}
203
204
205/*
206void testReorthonormalize()
207{
208 HEADER;
209 dMatrix3 R,I;
210 dMakeRandomMatrix (R,3,3,1.0);
211 for (int i=0; i<30; i++) dReorthonormalize (R);
212 dMultiply2 (I,R,R,3,3,3);
213 printf ("\t%s\n",cmpIdentityMat3 (I) ? "passed" : "FAILED");
214}
215*/
216
217
218void testPlaneSpace()
219{
220 HEADER;
221 dVector3 n,p,q;
222 int bad = 0;
223 for (int i=0; i<1000; i++) {
224 dMakeRandomVector (n,3,1.0);
225 dNormalize3 (n);
226 dPlaneSpace (n,p,q);
227 if (fabs(dDOT(n,p)) > tol) bad = 1;
228 if (fabs(dDOT(n,q)) > tol) bad = 1;
229 if (fabs(dDOT(p,q)) > tol) bad = 1;
230 if (fabs(dDOT(p,p)-1) > tol) bad = 1;
231 if (fabs(dDOT(q,q)-1) > tol) bad = 1;
232 }
233 printf ("\t%s\n", bad ? "FAILED" : "passed");
234}
235
236//****************************************************************************
237// test matrix functions
238
239#define MSIZE 21
240#define MSIZE4 24 // MSIZE rounded up to 4
241
242
243void testMatrixMultiply()
244{
245 // A is 2x3, B is 3x4, B2 is B except stored columnwise, C is 2x4
246 dReal A[8],B[12],A2[12],B2[16],C[8];
247 int i;
248
249 HEADER;
250 dSetZero (A,8);
251 for (i=0; i<3; i++) A[i] = i+2;
252 for (i=0; i<3; i++) A[i+4] = i+3+2;
253 for (i=0; i<12; i++) B[i] = i+8;
254 dSetZero (A2,12);
255 for (i=0; i<6; i++) A2[i+2*(i/2)] = A[i+i/3];
256 dSetZero (B2,16);
257 for (i=0; i<12; i++) B2[i+i/3] = B[i];
258
259 dMultiply0 (C,A,B,2,3,4);
260 if (C[0] != 116 || C[1] != 125 || C[2] != 134 || C[3] != 143 ||
261 C[4] != 224 || C[5] != 242 || C[6] != 260 || C[7] != 278)
262 printf ("\tFAILED (1)\n"); else printf ("\tpassed (1)\n");
263
264 dMultiply1 (C,A2,B,2,3,4);
265 if (C[0] != 160 || C[1] != 172 || C[2] != 184 || C[3] != 196 ||
266 C[4] != 196 || C[5] != 211 || C[6] != 226 || C[7] != 241)
267 printf ("\tFAILED (2)\n"); else printf ("\tpassed (2)\n");
268
269 dMultiply2 (C,A,B2,2,3,4);
270 if (C[0] != 83 || C[1] != 110 || C[2] != 137 || C[3] != 164 ||
271 C[4] != 164 || C[5] != 218 || C[6] != 272 || C[7] != 326)
272 printf ("\tFAILED (3)\n"); else printf ("\tpassed (3)\n");
273}
274
275
276void testSmallMatrixMultiply()
277{
278 dMatrix3 A,B,C,A2;
279 dVector3 a,a2,x;
280
281 HEADER;
282 dMakeRandomMatrix (A,3,3,1.0);
283 dMakeRandomMatrix (B,3,3,1.0);
284 dMakeRandomMatrix (C,3,3,1.0);
285 dMakeRandomMatrix (x,3,1,1.0);
286
287 // dMULTIPLY0_331()
288 dMULTIPLY0_331 (a,B,x);
289 dMultiply0 (a2,B,x,3,3,1);
290 printf ("\t%s (1)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
291 "passed");
292
293 // dMULTIPLY1_331()
294 dMULTIPLY1_331 (a,B,x);
295 dMultiply1 (a2,B,x,3,3,1);
296 printf ("\t%s (2)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
297 "passed");
298
299 // dMULTIPLY0_133
300 dMULTIPLY0_133 (a,x,B);
301 dMultiply0 (a2,x,B,1,3,3);
302 printf ("\t%s (3)\n",(dMaxDifference (a,a2,1,3) > tol) ? "FAILED" :
303 "passed");
304
305 // dMULTIPLY0_333()
306 dMULTIPLY0_333 (A,B,C);
307 dMultiply0 (A2,B,C,3,3,3);
308 printf ("\t%s (4)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
309 "passed");
310
311 // dMULTIPLY1_333()
312 dMULTIPLY1_333 (A,B,C);
313 dMultiply1 (A2,B,C,3,3,3);
314 printf ("\t%s (5)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
315 "passed");
316
317 // dMULTIPLY2_333()
318 dMULTIPLY2_333 (A,B,C);
319 dMultiply2 (A2,B,C,3,3,3);
320 printf ("\t%s (6)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
321 "passed");
322}
323
324
325void testCholeskyFactorization()
326{
327 dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE], C[MSIZE4*MSIZE], diff;
328 HEADER;
329 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
330 dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
331 memcpy (A,B,MSIZE4*MSIZE*sizeof(dReal));
332 if (dFactorCholesky (B,MSIZE)) printf ("\tpassed (1)\n");
333 else printf ("\tFAILED (1)\n");
334 dClearUpperTriangle (B,MSIZE);
335 dMultiply2 (C,B,B,MSIZE,MSIZE,MSIZE);
336 diff = dMaxDifference(A,C,MSIZE,MSIZE);
337 printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
338 diff > tol ? "FAILED" : "passed");
339}
340
341
342void testCholeskySolve()
343{
344 dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], b[MSIZE],x[MSIZE],btest[MSIZE],diff;
345 HEADER;
346
347 // get A,L = PD matrix
348 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
349 dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
350 memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
351
352 // get b,x = right hand side
353 dMakeRandomMatrix (b,MSIZE,1,1.0);
354 memcpy (x,b,MSIZE*sizeof(dReal));
355
356 // factor L
357 if (dFactorCholesky (L,MSIZE)) printf ("\tpassed (1)\n");
358 else printf ("\tFAILED (1)\n");
359 dClearUpperTriangle (L,MSIZE);
360
361 // solve A*x = b
362 dSolveCholesky (L,x,MSIZE);
363
364 // compute A*x and compare it with b
365 dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
366 diff = dMaxDifference(b,btest,MSIZE,1);
367 printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
368 diff > tol ? "FAILED" : "passed");
369}
370
371
372void testInvertPDMatrix()
373{
374 int i,j,ok;
375 dReal A[MSIZE4*MSIZE], Ainv[MSIZE4*MSIZE], I[MSIZE4*MSIZE];
376 HEADER;
377
378 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
379 dMultiply2 (Ainv,A,A,MSIZE,MSIZE,MSIZE);
380 memcpy (A,Ainv,MSIZE4*MSIZE*sizeof(dReal));
381 dSetZero (Ainv,MSIZE4*MSIZE);
382
383 if (dInvertPDMatrix (A,Ainv,MSIZE))
384 printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n");
385 dMultiply0 (I,A,Ainv,MSIZE,MSIZE,MSIZE);
386
387 // compare with identity
388 ok = 1;
389 for (i=0; i<MSIZE; i++) {
390 for (j=0; j<MSIZE; j++) {
391 if (i != j) if (cmp (I[i*MSIZE4+j],0.0)==0) ok = 0;
392 }
393 }
394 for (i=0; i<MSIZE; i++) {
395 if (cmp (I[i*MSIZE4+i],1.0)==0) ok = 0;
396 }
397 if (ok) printf ("\tpassed (2)\n"); else printf ("\tFAILED (2)\n");
398}
399
400
401void testIsPositiveDefinite()
402{
403 dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE];
404 HEADER;
405 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
406 dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
407 printf ("\t%s\n",dIsPositiveDefinite(A,MSIZE) ? "FAILED (1)":"passed (1)");
408 printf ("\t%s\n",dIsPositiveDefinite(B,MSIZE) ? "passed (2)":"FAILED (2)");
409}
410
411
412void testFastLDLTFactorization()
413{
414 int i,j;
415 dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], DL[MSIZE4*MSIZE],
416 ATEST[MSIZE4*MSIZE], d[MSIZE], diff;
417 HEADER;
418 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
419 dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
420 memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
421
422 dFactorLDLT (L,d,MSIZE,MSIZE4);
423 dClearUpperTriangle (L,MSIZE);
424 for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
425
426 dSetZero (DL,MSIZE4*MSIZE);
427 for (i=0; i<MSIZE; i++) {
428 for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
429 }
430
431 dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
432 diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
433 printf ("\tmaximum difference = %.6e - %s\n",diff,
434 diff > tol ? "FAILED" : "passed");
435}
436
437
438void testSolveLDLT()
439{
440 dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], x[MSIZE],
441 b[MSIZE], btest[MSIZE], diff;
442 HEADER;
443 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
444 dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
445 memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
446
447 dMakeRandomMatrix (b,MSIZE,1,1.0);
448 memcpy (x,b,MSIZE*sizeof(dReal));
449
450 dFactorLDLT (L,d,MSIZE,MSIZE4);
451 dSolveLDLT (L,d,x,MSIZE,MSIZE4);
452
453 dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
454 diff = dMaxDifference(b,btest,MSIZE,1);
455 printf ("\tmaximum difference = %.6e - %s\n",diff,
456 diff > tol ? "FAILED" : "passed");
457}
458
459
460void testLDLTAddTL()
461{
462 int i,j;
463 dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], a[MSIZE],
464 DL[MSIZE4*MSIZE], ATEST[MSIZE4*MSIZE], diff;
465 HEADER;
466
467 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
468 dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
469 memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
470 dFactorLDLT (L,d,MSIZE,MSIZE4);
471
472 // delete first row and column of factorization
473 for (i=0; i<MSIZE; i++) a[i] = -A[i*MSIZE4];
474 a[0] += 1;
475 dLDLTAddTL (L,d,a,MSIZE,MSIZE4);
476 for (i=1; i<MSIZE; i++) L[i*MSIZE4] = 0;
477 d[0] = 1;
478
479 // get modified L*D*L'
480 dClearUpperTriangle (L,MSIZE);
481 for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
482 dSetZero (DL,MSIZE4*MSIZE);
483 for (i=0; i<MSIZE; i++) {
484 for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
485 }
486 dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
487
488 // compare it to A with its first row/column removed
489 for (i=1; i<MSIZE; i++) A[i*MSIZE4] = A[i] = 0;
490 A[0] = 1;
491 diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
492 printf ("\tmaximum difference = %.6e - %s\n",diff,
493 diff > tol ? "FAILED" : "passed");
494}
495
496
497void testLDLTRemove()
498{
499 int i,j,r,p[MSIZE];
500 dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE],
501 L2[MSIZE4*MSIZE], d2[MSIZE], DL2[MSIZE4*MSIZE],
502 Atest1[MSIZE4*MSIZE], Atest2[MSIZE4*MSIZE], diff, maxdiff;
503 HEADER;
504
505 // make array of A row pointers
506 dReal *Arows[MSIZE];
507 for (i=0; i<MSIZE; i++) Arows[i] = A+i*MSIZE4;
508
509 // fill permutation vector
510 for (i=0; i<MSIZE; i++) p[i]=i;
511
512 dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
513 dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
514 memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
515 dFactorLDLT (L,d,MSIZE,MSIZE4);
516
517 maxdiff = 1e10;
518 for (r=0; r<MSIZE; r++) {
519 // get Atest1 = A with row/column r removed
520 memcpy (Atest1,A,MSIZE4*MSIZE*sizeof(dReal));
521 dRemoveRowCol (Atest1,MSIZE,MSIZE4,r);
522
523 // test that the row/column removal worked
524 int bad = 0;
525 for (i=0; i<MSIZE; i++) {
526 for (j=0; j<MSIZE; j++) {
527 if (i != r && j != r) {
528 int ii = i;
529 int jj = j;
530 if (ii >= r) ii--;
531 if (jj >= r) jj--;
532 if (A[i*MSIZE4+j] != Atest1[ii*MSIZE4+jj]) bad = 1;
533 }
534 }
535 }
536 if (bad) printf ("\trow/col removal FAILED for row %d\n",r);
537
538 // zero out last row/column of Atest1
539 for (i=0; i<MSIZE; i++) {
540 Atest1[(MSIZE-1)*MSIZE4+i] = 0;
541 Atest1[i*MSIZE4+MSIZE-1] = 0;
542 }
543
544 // get L2*D2*L2' = adjusted factorization to remove that row
545 memcpy (L2,L,MSIZE4*MSIZE*sizeof(dReal));
546 memcpy (d2,d,MSIZE*sizeof(dReal));
547 dLDLTRemove (/*A*/ Arows,p,L2,d2,MSIZE,MSIZE,r,MSIZE4);
548
549 // get Atest2 = L2*D2*L2'
550 dClearUpperTriangle (L2,MSIZE);
551 for (i=0; i<(MSIZE-1); i++) L2[i*MSIZE4+i] = 1.0;
552 for (i=0; i<MSIZE; i++) L2[(MSIZE-1)*MSIZE4+i] = 0;
553 d2[MSIZE-1] = 1;
554 dSetZero (DL2,MSIZE4*MSIZE);
555 for (i=0; i<(MSIZE-1); i++) {
556 for (j=0; j<MSIZE-1; j++) DL2[i*MSIZE4+j] = L2[i*MSIZE4+j] / d2[j];
557 }
558
559 dMultiply2 (Atest2,L2,DL2,MSIZE,MSIZE,MSIZE);
560
561 diff = dMaxDifference(Atest1,Atest2,MSIZE,MSIZE);
562 if (diff < maxdiff) maxdiff = diff;
563
564 /*
565 dPrintMatrix (Atest1,MSIZE,MSIZE);
566 printf ("\n");
567 dPrintMatrix (Atest2,MSIZE,MSIZE);
568 printf ("\n");
569 */
570 }
571 printf ("\tmaximum difference = %.6e - %s\n",maxdiff,
572 maxdiff > tol ? "FAILED" : "passed");
573}
574
575//****************************************************************************
576// test mass stuff
577
578#define NUMP 10 // number of particles
579
580
581void printMassParams (dMass *m)
582{
583 printf ("mass = %.4f\n",m->mass);
584 printf ("com = (%.4f,%.4f,%.4f)\n",m->c[0],m->c[1],m->c[2]);
585 printf ("I = [ %10.4f %10.4f %10.4f ]\n"
586 " [ %10.4f %10.4f %10.4f ]\n"
587 " [ %10.4f %10.4f %10.4f ]\n",
588 m->_I(0,0),m->_I(0,1),m->_I(0,2),
589 m->_I(1,0),m->_I(1,1),m->_I(1,2),
590 m->_I(2,0),m->_I(2,1),m->_I(2,2));
591}
592
593
594void compareMassParams (dMass *m1, dMass *m2, char *msg)
595{
596 int i,j,ok = 1;
597 if (!(cmp(m1->mass,m2->mass) && cmp(m1->c[0],m2->c[0]) &&
598 cmp(m1->c[1],m2->c[1]) && cmp(m1->c[2],m2->c[2])))
599 ok = 0;
600 for (i=0; i<3; i++) for (j=0; j<3; j++)
601 if (cmp (m1->_I(i,j),m2->_I(i,j))==0) ok = 0;
602 if (ok) printf ("\tpassed (%s)\n",msg); else printf ("\tFAILED (%s)\n",msg);
603}
604
605
606// compute the mass parameters of a particle set
607
608void computeMassParams (dMass *m, dReal q[NUMP][3], dReal pm[NUMP])
609{
610 int i,j;
611 dMassSetZero (m);
612 for (i=0; i<NUMP; i++) {
613 m->mass += pm[i];
614 for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
615 m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
616 m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
617 m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
618 m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
619 m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
620 m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
621 }
622 for (j=0; j<3; j++) m->c[j] /= m->mass;
623 m->_I(1,0) = m->_I(0,1);
624 m->_I(2,0) = m->_I(0,2);
625 m->_I(2,1) = m->_I(1,2);
626}
627
628
629void testMassFunctions()
630{
631 dMass m;
632 int i,j;
633 dReal q[NUMP][3]; // particle positions
634 dReal pm[NUMP]; // particle masses
635 dMass m1,m2;
636 dMatrix3 R;
637
638 HEADER;
639
640 printf ("\t");
641 dMassSetZero (&m);
642 TRAP_MESSAGE (dMassSetParameters (&m,10, 0,0,0, 1,2,3, 4,5,6),
643 printf (" FAILED (1)\n"), printf (" passed (1)\n"));
644
645 printf ("\t");
646 dMassSetZero (&m);
647 TRAP_MESSAGE (dMassSetParameters (&m,10, 0.1,0.2,0.15, 3,5,14, 3.1,3.2,4),
648 printf (" passed (2)\n") , printf (" FAILED (2)\n"));
649 if (m.mass==10 && m.c[0]==REAL(0.1) && m.c[1]==REAL(0.2) &&
650 m.c[2]==REAL(0.15) && m._I(0,0)==3 && m._I(1,1)==5 && m._I(2,2)==14 &&
651 m._I(0,1)==REAL(3.1) && m._I(0,2)==REAL(3.2) && m._I(1,2)==4 &&
652 m._I(1,0)==REAL(3.1) && m._I(2,0)==REAL(3.2) && m._I(2,1)==4)
653 printf ("\tpassed (3)\n"); else printf ("\tFAILED (3)\n");
654
655 dMassSetZero (&m);
656 dMassSetSphere (&m,1.4, 0.86);
657 if (cmp(m.mass,3.73002719949386) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
658 cmp(m._I(0,0),1.10349124669826) &&
659 cmp(m._I(1,1),1.10349124669826) &&
660 cmp(m._I(2,2),1.10349124669826) &&
661 m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
662 m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
663 printf ("\tpassed (4)\n"); else printf ("\tFAILED (4)\n");
664
665 dMassSetZero (&m);
666 dMassSetCapsule (&m,1.3,1,0.76,1.53);
667 if (cmp(m.mass,5.99961928996029) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
668 cmp(m._I(0,0),1.59461986077384) &&
669 cmp(m._I(1,1),4.57537403079093) &&
670 cmp(m._I(2,2),4.57537403079093) &&
671 m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
672 m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
673 printf ("\tpassed (5)\n"); else printf ("\tFAILED (5)\n");
674
675 dMassSetZero (&m);
676 dMassSetBox (&m,0.27,3,4,5);
677 if (cmp(m.mass,16.2) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
678 cmp(m._I(0,0),55.35) && cmp(m._I(1,1),45.9) && cmp(m._I(2,2),33.75) &&
679 m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
680 m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
681 printf ("\tpassed (6)\n"); else printf ("\tFAILED (6)\n");
682
683 // test dMassAdjust?
684
685 // make random particles and compute the mass, COM and inertia, then
686 // translate and repeat.
687 for (i=0; i<NUMP; i++) {
688 pm[i] = dRandReal()+0.5;
689 for (j=0; j<3; j++) {
690 q[i][j] = 2.0*(dRandReal()-0.5);
691 }
692 }
693 computeMassParams (&m1,q,pm);
694 memcpy (&m2,&m1,sizeof(dMass));
695 dMassTranslate (&m2,1,2,-3);
696 for (i=0; i<NUMP; i++) {
697 q[i][0] += 1;
698 q[i][1] += 2;
699 q[i][2] -= 3;
700 }
701 computeMassParams (&m1,q,pm);
702 compareMassParams (&m1,&m2,"7");
703
704 // rotate the masses
705 _R(0,0) = -0.87919618797635;
706 _R(0,1) = 0.15278881840384;
707 _R(0,2) = -0.45129772879842;
708 _R(1,0) = -0.47307856232664;
709 _R(1,1) = -0.39258064912909;
710 _R(1,2) = 0.78871864932708;
711 _R(2,0) = -0.05666336483842;
712 _R(2,1) = 0.90693771059546;
713 _R(2,2) = 0.41743652473765;
714 dMassRotate (&m2,R);
715 for (i=0; i<NUMP; i++) {
716 dReal a[3];
717 dMultiply0 (a,&_R(0,0),&q[i][0],3,3,1);
718 q[i][0] = a[0];
719 q[i][1] = a[1];
720 q[i][2] = a[2];
721 }
722 computeMassParams (&m1,q,pm);
723 compareMassParams (&m1,&m2,"8");
724}
725
726//****************************************************************************
727// test rotation stuff
728
729void makeRandomRotation (dMatrix3 R)
730{
731 dReal *u1 = R, *u2=R+4, *u3=R+8;
732 dMakeRandomVector (u1,3,1.0);
733 dNormalize3 (u1);
734 dMakeRandomVector (u2,3,1.0);
735 dReal d = dDOT(u1,u2);
736 u2[0] -= d*u1[0];
737 u2[1] -= d*u1[1];
738 u2[2] -= d*u1[2];
739 dNormalize3 (u2);
740 dCROSS (u3,=,u1,u2);
741}
742
743
744void testRtoQandQtoR()
745{
746 HEADER;
747 dMatrix3 R,I,R2;
748 dQuaternion q;
749 int i;
750
751 // test makeRandomRotation()
752 makeRandomRotation (R);
753 dMultiply2 (I,R,R,3,3,3);
754 printf ("\tmakeRandomRotation() - %s (1)\n",
755 cmpIdentityMat3(I) ? "passed" : "FAILED");
756
757 // test QtoR() on random normalized quaternions
758 int ok = 1;
759 for (i=0; i<100; i++) {
760 dMakeRandomVector (q,4,1.0);
761 dNormalize4 (q);
762 dQtoR (q,R);
763 dMultiply2 (I,R,R,3,3,3);
764 if (cmpIdentityMat3(I)==0) ok = 0;
765 }
766 printf ("\tQtoR() orthonormality %s (2)\n", ok ? "passed" : "FAILED");
767
768 // test R -> Q -> R works
769 dReal maxdiff=0;
770 for (i=0; i<100; i++) {
771 makeRandomRotation (R);
772 dRtoQ (R,q);
773 dQtoR (q,R2);
774 dReal diff = dMaxDifference (R,R2,3,3);
775 if (diff > maxdiff) maxdiff = diff;
776 }
777 printf ("\tmaximum difference = %e - %s (3)\n",maxdiff,
778 (maxdiff > tol) ? "FAILED" : "passed");
779}
780
781
782void testQuaternionMultiply()
783{
784 HEADER;
785 dMatrix3 RA,RB,RC,Rtest;
786 dQuaternion qa,qb,qc;
787 dReal diff,maxdiff=0;
788
789 for (int i=0; i<100; i++) {
790 makeRandomRotation (RB);
791 makeRandomRotation (RC);
792 dRtoQ (RB,qb);
793 dRtoQ (RC,qc);
794
795 dMultiply0 (RA,RB,RC,3,3,3);
796 dQMultiply0 (qa,qb,qc);
797 dQtoR (qa,Rtest);
798 diff = dMaxDifference (Rtest,RA,3,3);
799 if (diff > maxdiff) maxdiff = diff;
800
801 dMultiply1 (RA,RB,RC,3,3,3);
802 dQMultiply1 (qa,qb,qc);
803 dQtoR (qa,Rtest);
804 diff = dMaxDifference (Rtest,RA,3,3);
805 if (diff > maxdiff) maxdiff = diff;
806
807 dMultiply2 (RA,RB,RC,3,3,3);
808 dQMultiply2 (qa,qb,qc);
809 dQtoR (qa,Rtest);
810 diff = dMaxDifference (Rtest,RA,3,3);
811 if (diff > maxdiff) maxdiff = diff;
812
813 dMultiply0 (RA,RC,RB,3,3,3);
814 transpose3x3 (RA);
815 dQMultiply3 (qa,qb,qc);
816 dQtoR (qa,Rtest);
817 diff = dMaxDifference (Rtest,RA,3,3);
818 if (diff > maxdiff) maxdiff = diff;
819 }
820 printf ("\tmaximum difference = %e - %s\n",maxdiff,
821 (maxdiff > tol) ? "FAILED" : "passed");
822}
823
824
825void testRotationFunctions()
826{
827 dMatrix3 R1;
828 HEADER;
829
830 printf ("\tdRSetIdentity - ");
831 dMakeRandomMatrix (R1,3,3,1.0);
832 dRSetIdentity (R1);
833 if (cmpIdentityMat3(R1)) printf ("passed\n"); else printf ("FAILED\n");
834
835 printf ("\tdRFromAxisAndAngle - ");
836
837 printf ("\n");
838 printf ("\tdRFromEulerAngles - ");
839
840 printf ("\n");
841 printf ("\tdRFrom2Axes - ");
842
843 printf ("\n");
844}
845
846//****************************************************************************
847
848#include "../src/array.h"
849#include "../src/array.cpp"
850
851// matrix header on the stack
852
853class dMatrixComparison {
854 struct dMatInfo;
855 dArray<dMatInfo*> mat;
856 int afterfirst,index;
857
858public:
859 dMatrixComparison();
860 ~dMatrixComparison();
861
862 dReal nextMatrix (dReal *A, int n, int m, int lower_tri, char *name, ...);
863 // add a new n*m matrix A to the sequence. the name of the matrix is given
864 // by the printf-style arguments (name,...). if this is the first sequence
865 // then this object will simply record the matrices and return 0.
866 // if this the second or subsequent sequence then this object will compare
867 // the matrices with the first sequence, and report any differences.
868 // the matrix error will be returned. if `lower_tri' is 1 then only the
869 // lower triangle of the matrix (including the diagonal) will be compared
870 // (the matrix must be square).
871
872 void end();
873 // end a sequence.
874
875 void reset();
876 // restarts the object, so the next sequence will be the first sequence.
877
878 void dump();
879 // print out info about all the matrices in the sequence
880};
881
882struct dMatrixComparison::dMatInfo {
883 int n,m; // size of matrix
884 char name[128]; // name of the matrix
885 dReal *data; // matrix data
886 int size; // size of `data'
887};
888
889
890
891dMatrixComparison::dMatrixComparison()
892{
893 afterfirst = 0;
894 index = 0;
895}
896
897
898dMatrixComparison::~dMatrixComparison()
899{
900 reset();
901}
902
903
904dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
905 char *name, ...)
906{
907 if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
908 int num = n*dPAD(m);
909
910 if (afterfirst==0) {
911 dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
912 mi->n = n;
913 mi->m = m;
914 mi->size = num * sizeof(dReal);
915 mi->data = (dReal*) dAlloc (mi->size);
916 memcpy (mi->data,A,mi->size);
917
918 va_list ap;
919 va_start (ap,name);
920 vsprintf (mi->name,name,ap);
921 if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
922
923 mat.push (mi);
924 return 0;
925 }
926 else {
927 if (lower_tri && n != m)
928 dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
929 if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
930 dMatInfo *mp = mat[index];
931 index++;
932
933 dMatInfo mi;
934 va_list ap;
935 va_start (ap,name);
936 vsprintf (mi.name,name,ap);
937 if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
938
939 if (strcmp(mp->name,mi.name) != 0)
940 dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
941 mp->name,mi.name);
942 if (mp->n != n || mp->m != m)
943 dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
944 mp->n,mp->m,n,m);
945
946 dReal maxdiff;
947 if (lower_tri) {
948 maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
949 }
950 else {
951 maxdiff = dMaxDifference (A,mp->data,n,m);
952 }
953 if (maxdiff > tol)
954 dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
955 "error=%.4e)",n,m,mi.name,maxdiff);
956 return maxdiff;
957 }
958}
959
960
961void dMatrixComparison::end()
962{
963 if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
964 afterfirst = 1;
965 index = 0;
966}
967
968
969void dMatrixComparison::reset()
970{
971 for (int i=0; i<mat.size(); i++) {
972 dFree (mat[i]->data,mat[i]->size);
973 dFree (mat[i],sizeof(dMatInfo));
974 }
975 mat.setSize (0);
976 afterfirst = 0;
977 index = 0;
978}
979
980
981void dMatrixComparison::dump()
982{
983 for (int i=0; i<mat.size(); i++)
984 printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
985}
986
987//****************************************************************************
988// unit test
989
990#include <setjmp.h>
991
992// static jmp_buf jump_buffer;
993
994static void myDebug (int num, const char *msg, va_list ap)
995{
996 // printf ("(Error %d: ",num);
997 // vprintf (msg,ap);
998 // printf (")\n");
999 longjmp (jump_buffer,1);
1000}
1001
1002
1003extern "C" void dTestMatrixComparison()
1004{
1005 volatile int i;
1006 printf ("dTestMatrixComparison()\n");
1007 dMessageFunction *orig_debug = dGetDebugHandler();
1008
1009 dMatrixComparison mc;
1010 dReal A[50*50];
1011
1012 // make first sequence
1013 unsigned long seed = dRandGetSeed();
1014 for (i=1; i<49; i++) {
1015 dMakeRandomMatrix (A,i,i+1,1.0);
1016 mc.nextMatrix (A,i,i+1,0,"A%d",i);
1017 }
1018 mc.end();
1019
1020 //mc.dump();
1021
1022 // test identical sequence
1023 dSetDebugHandler (&myDebug);
1024 dRandSetSeed (seed);
1025 if (setjmp (jump_buffer)) {
1026 printf ("\tFAILED (1)\n");
1027 }
1028 else {
1029 for (i=1; i<49; i++) {
1030 dMakeRandomMatrix (A,i,i+1,1.0);
1031 mc.nextMatrix (A,i,i+1,0,"A%d",i);
1032 }
1033 mc.end();
1034 printf ("\tpassed (1)\n");
1035 }
1036 dSetDebugHandler (orig_debug);
1037
1038 // test broken sequences (with matrix error)
1039 dRandSetSeed (seed);
1040 volatile int passcount = 0;
1041 for (i=1; i<49; i++) {
1042 if (setjmp (jump_buffer)) {
1043 passcount++;
1044 }
1045 else {
1046 dSetDebugHandler (&myDebug);
1047 dMakeRandomMatrix (A,i,i+1,1.0);
1048 A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
1049 mc.nextMatrix (A,i,i+1,0,"A%d",i);
1050 dSetDebugHandler (orig_debug);
1051 }
1052 }
1053 mc.end();
1054 printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
1055
1056 // test broken sequences (with name error)
1057 dRandSetSeed (seed);
1058 passcount = 0;
1059 for (i=1; i<49; i++) {
1060 if (setjmp (jump_buffer)) {
1061 passcount++;
1062 }
1063 else {
1064 dSetDebugHandler (&myDebug);
1065 dMakeRandomMatrix (A,i,i+1,1.0);
1066 mc.nextMatrix (A,i,i+1,0,"B%d",i);
1067 dSetDebugHandler (orig_debug);
1068 }
1069 }
1070 mc.end();
1071 printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
1072
1073 // test identical sequence again
1074 dSetDebugHandler (&myDebug);
1075 dRandSetSeed (seed);
1076 if (setjmp (jump_buffer)) {
1077 printf ("\tFAILED (4)\n");
1078 }
1079 else {
1080 for (i=1; i<49; i++) {
1081 dMakeRandomMatrix (A,i,i+1,1.0);
1082 mc.nextMatrix (A,i,i+1,0,"A%d",i);
1083 }
1084 mc.end();
1085 printf ("\tpassed (4)\n");
1086 }
1087 dSetDebugHandler (orig_debug);
1088}
1089
1090//****************************************************************************
1091
1092// internal unit tests
1093extern "C" void dTestDataStructures();
1094extern "C" void dTestMatrixComparison();
1095extern "C" void dTestSolveLCP();
1096
1097
1098int main()
1099{
1100 dInitODE();
1101 testRandomNumberGenerator();
1102 testInfinity();
1103 testPad();
1104 testCrossProduct();
1105 testSetZero();
1106 testNormalize3();
1107 //testReorthonormalize(); ... not any more
1108 testPlaneSpace();
1109 testMatrixMultiply();
1110 testSmallMatrixMultiply();
1111 testCholeskyFactorization();
1112 testCholeskySolve();
1113 testInvertPDMatrix();
1114 testIsPositiveDefinite();
1115 testFastLDLTFactorization();
1116 testSolveLDLT();
1117 testLDLTAddTL();
1118 testLDLTRemove();
1119 testMassFunctions();
1120 testRtoQandQtoR();
1121 testQuaternionMultiply();
1122 testRotationFunctions();
1123 dTestMatrixComparison();
1124 dTestSolveLCP();
1125 // dTestDataStructures();
1126 dCloseODE();
1127 return 0;
1128}
diff --git a/libraries/ode-0.9/ode/demo/demo_plane2d.cpp b/libraries/ode-0.9/ode/demo/demo_plane2d.cpp
deleted file mode 100644
index 3ba4df8..0000000
--- a/libraries/ode-0.9/ode/demo/demo_plane2d.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
1// Test my Plane2D constraint.
2// Uses ode-0.35 collision API.
3
4# include <stdio.h>
5# include <stdlib.h>
6# include <math.h>
7# include <ode/ode.h>
8# include <drawstuff/drawstuff.h>
9
10# define drand48() ((double) (((double) rand()) / ((double) RAND_MAX)))
11
12# define N_BODIES 40
13# define STAGE_SIZE 8.0 // in m
14
15# define TIME_STEP 0.01
16# define K_SPRING 10.0
17# define K_DAMP 10.0
18
19
20static dWorld dyn_world;
21static dBody dyn_bodies[N_BODIES];
22static dReal bodies_sides[N_BODIES][3];
23
24static dSpaceID coll_space_id;
25static dJointID plane2d_joint_ids[N_BODIES];
26static dJointGroup
27 coll_contacts;
28
29
30
31static void cb_start ()
32/*************************/
33{
34 static float xyz[3] = { 0.5f*STAGE_SIZE, 0.5f*STAGE_SIZE, 0.65f*STAGE_SIZE};
35 static float hpr[3] = { 90.0f, -90.0f, 0 };
36
37 dsSetViewpoint (xyz, hpr);
38}
39
40
41
42static void cb_near_collision (void *data, dGeomID o1, dGeomID o2)
43/********************************************************************/
44{
45 dBodyID b1 = dGeomGetBody (o1);
46 dBodyID b2 = dGeomGetBody (o2);
47 dContact contact;
48
49
50 // exit without doing anything if the two bodies are static
51 if (b1 == 0 && b2 == 0)
52 return;
53
54 // exit without doing anything if the two bodies are connected by a joint
55 if (b1 && b2 && dAreConnected (b1, b2))
56 {
57 /* MTRAP; */
58 return;
59 }
60
61 contact.surface.mode = 0;
62 contact.surface.mu = 0; // frictionless
63
64 if (dCollide (o1, o2, 1, &contact.geom, sizeof (dContactGeom)))
65 {
66 dJointID c = dJointCreateContact (dyn_world.id(),
67 coll_contacts.id (), &contact);
68 dJointAttach (c, b1, b2);
69 }
70}
71
72
73static void track_to_pos (dBody &body, dJointID joint_id,
74 dReal target_x, dReal target_y)
75/************************************************************************/
76{
77 dReal curr_x = body.getPosition()[0];
78 dReal curr_y = body.getPosition()[1];
79
80 dJointSetPlane2DXParam (joint_id, dParamVel, 1 * (target_x - curr_x));
81 dJointSetPlane2DYParam (joint_id, dParamVel, 1 * (target_y - curr_y));
82}
83
84
85
86static void cb_sim_step (int pause)
87/*************************************/
88{
89 if (! pause)
90 {
91 static dReal angle = 0;
92
93 angle += REAL( 0.01 );
94
95 track_to_pos (dyn_bodies[0], plane2d_joint_ids[0],
96 dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * cos (angle) ),
97 dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * sin (angle) ));
98
99 /* double f0 = 0.001; */
100 /* for (int b = 0; b < N_BODIES; b ++) */
101 /* { */
102 /* double p = 1 + b / (double) N_BODIES; */
103 /* double q = 2 - b / (double) N_BODIES; */
104 /* dyn_bodies[b].addForce (f0 * cos (p*angle), f0 * sin (q*angle), 0); */
105 /* } */
106 /* dyn_bodies[0].addTorque (0, 0, 0.1); */
107
108 const int n = 10;
109 for (int i = 0; i < n; i ++)
110 {
111 dSpaceCollide (coll_space_id, 0, &cb_near_collision);
112 dyn_world.step (dReal(TIME_STEP/n));
113 coll_contacts.empty ();
114 }
115 }
116
117# if 1 /* [ */
118 {
119 // @@@ hack Plane2D constraint error reduction here:
120 for (int b = 0; b < N_BODIES; b ++)
121 {
122 const dReal *rot = dBodyGetAngularVel (dyn_bodies[b].id());
123 const dReal *quat_ptr;
124 dReal quat[4],
125 quat_len;
126
127
128 quat_ptr = dBodyGetQuaternion (dyn_bodies[b].id());
129 quat[0] = quat_ptr[0];
130 quat[1] = 0;
131 quat[2] = 0;
132 quat[3] = quat_ptr[3];
133 quat_len = sqrt (quat[0] * quat[0] + quat[3] * quat[3]);
134 quat[0] /= quat_len;
135 quat[3] /= quat_len;
136 dBodySetQuaternion (dyn_bodies[b].id(), quat);
137 dBodySetAngularVel (dyn_bodies[b].id(), 0, 0, rot[2]);
138 }
139 }
140# endif /* ] */
141
142
143# if 0 /* [ */
144 {
145 // @@@ friction
146 for (int b = 0; b < N_BODIES; b ++)
147 {
148 const dReal *vel = dBodyGetLinearVel (dyn_bodies[b].id()),
149 *rot = dBodyGetAngularVel (dyn_bodies[b].id());
150 dReal s = 1.00;
151 dReal t = 0.99;
152
153 dBodySetLinearVel (dyn_bodies[b].id(), s*vel[0],s*vel[1],s*vel[2]);
154 dBodySetAngularVel (dyn_bodies[b].id(),t*rot[0],t*rot[1],t*rot[2]);
155 }
156 }
157# endif /* ] */
158
159
160 {
161 // ode drawstuff
162
163 dsSetTexture (DS_WOOD);
164 for (int b = 0; b < N_BODIES; b ++)
165 {
166 if (b == 0)
167 dsSetColor (1.0, 0.5, 1.0);
168 else
169 dsSetColor (0, 0.5, 1.0);
170#ifdef dDOUBLE
171 dsDrawBoxD (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
172#else
173 dsDrawBox (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
174#endif
175 }
176 }
177}
178
179
180
181extern int main
182/******************/
183(
184 int argc,
185 char **argv
186)
187{
188 int b;
189 dsFunctions drawstuff_functions;
190
191
192 dInitODE();
193
194 // dynamic world
195
196 dReal cf_mixing;// = 1 / TIME_STEP * K_SPRING + K_DAMP;
197 dReal err_reduct;// = TIME_STEP * K_SPRING * cf_mixing;
198 err_reduct = REAL( 0.5 );
199 cf_mixing = REAL( 0.001 );
200 dWorldSetERP (dyn_world.id (), err_reduct);
201 dWorldSetCFM (dyn_world.id (), cf_mixing);
202 dyn_world.setGravity (0, 0.0, -1.0);
203
204 coll_space_id = dSimpleSpaceCreate (0);
205
206 // dynamic bodies
207 for (b = 0; b < N_BODIES; b ++)
208 {
209 int l = (int) (1 + sqrt ((double) N_BODIES));
210 dReal x = dReal( (0.5 + (b / l)) / l * STAGE_SIZE );
211 dReal y = dReal( (0.5 + (b % l)) / l * STAGE_SIZE );
212 dReal z = REAL( 1.0 ) + REAL( 0.1 ) * (dReal)drand48();
213
214 bodies_sides[b][0] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
215 bodies_sides[b][1] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
216 bodies_sides[b][2] = z;
217
218 dyn_bodies[b].create (dyn_world);
219 dyn_bodies[b].setPosition (x, y, z/2);
220 dyn_bodies[b].setData ((void*) (size_t)b);
221 dBodySetLinearVel (dyn_bodies[b].id (),
222 dReal( 3 * (drand48 () - 0.5) ),
223 dReal( 3 * (drand48 () - 0.5) ), 0);
224
225 dMass m;
226 m.setBox (1, bodies_sides[b][0],bodies_sides[b][1],bodies_sides[b][2]);
227 m.adjust (REAL(0.1) * bodies_sides[b][0] * bodies_sides[b][1]);
228 dyn_bodies[b].setMass (&m);
229
230 plane2d_joint_ids[b] = dJointCreatePlane2D (dyn_world.id (), 0);
231 dJointAttach (plane2d_joint_ids[b], dyn_bodies[b].id (), 0);
232 }
233
234 dJointSetPlane2DXParam (plane2d_joint_ids[0], dParamFMax, 10);
235 dJointSetPlane2DYParam (plane2d_joint_ids[0], dParamFMax, 10);
236
237
238 // collision geoms and joints
239 dCreatePlane (coll_space_id, 1, 0, 0, 0);
240 dCreatePlane (coll_space_id, -1, 0, 0, -STAGE_SIZE);
241 dCreatePlane (coll_space_id, 0, 1, 0, 0);
242 dCreatePlane (coll_space_id, 0, -1, 0, -STAGE_SIZE);
243
244 for (b = 0; b < N_BODIES; b ++)
245 {
246 dGeomID coll_box_id;
247 coll_box_id = dCreateBox (coll_space_id,
248 bodies_sides[b][0], bodies_sides[b][1], bodies_sides[b][2]);
249 dGeomSetBody (coll_box_id, dyn_bodies[b].id ());
250 }
251
252 coll_contacts.create (0);
253
254 {
255 // simulation loop (by drawstuff lib)
256 drawstuff_functions.version = DS_VERSION;
257 drawstuff_functions.start = &cb_start;
258 drawstuff_functions.step = &cb_sim_step;
259 drawstuff_functions.command = 0;
260 drawstuff_functions.stop = 0;
261 drawstuff_functions.path_to_textures = "../../drawstuff/textures";
262
263 dsSimulationLoop (argc, argv, 352,288,&drawstuff_functions);
264 }
265
266 dCloseODE();
267 return 0;
268}
diff --git a/libraries/ode-0.9/ode/demo/demo_slider.cpp b/libraries/ode-0.9/ode/demo/demo_slider.cpp
deleted file mode 100644
index 5de08b0..0000000
--- a/libraries/ode-0.9/ode/demo/demo_slider.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30// select correct drawing functions
31#ifdef dDOUBLE
32#define dsDrawBox dsDrawBoxD
33#endif
34
35
36// some constants
37#define SIDE (0.5f) // side length of a box
38#define MASS (1.0) // mass of a box
39
40
41// dynamics and collision objects
42static dWorldID world;
43static dBodyID body[2];
44static dJointID slider;
45
46
47// state set by keyboard commands
48static int occasional_error = 0;
49
50
51// start simulation - set viewpoint
52
53static void start()
54{
55 static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
56 static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
57 dsSetViewpoint (xyz,hpr);
58 printf ("Press 'e' to start/stop occasional error.\n");
59}
60
61
62// called when a key pressed
63
64static void command (int cmd)
65{
66 if (cmd == 'e' || cmd == 'E') {
67 occasional_error ^= 1;
68 }
69}
70
71
72// simulation loop
73
74static void simLoop (int pause)
75{
76 const dReal kd = -0.3; // angular damping constant
77 const dReal ks = 0.5; // spring constant
78 if (!pause) {
79 // add an oscillating torque to body 0, and also damp its rotational motion
80 static dReal a=0;
81 const dReal *w = dBodyGetAngularVel (body[0]);
82 dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a));
83 a += 0.01;
84
85 // add a spring force to keep the bodies together, otherwise they will
86 // fly apart along the slider axis.
87 const dReal *p1 = dBodyGetPosition (body[0]);
88 const dReal *p2 = dBodyGetPosition (body[1]);
89 dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]),
90 ks*(p2[2]-p1[2]));
91 dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]),
92 ks*(p1[2]-p2[2]));
93
94 // occasionally re-orient one of the bodies to create a deliberate error.
95 if (occasional_error) {
96 static int count = 0;
97 if ((count % 20)==0) {
98 // randomly adjust orientation of body[0]
99 const dReal *R1;
100 dMatrix3 R2,R3;
101 R1 = dBodyGetRotation (body[0]);
102 dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
103 dRandReal()-0.5,dRandReal()-0.5);
104 dMultiply0 (R3,R1,R2,3,3,3);
105 dBodySetRotation (body[0],R3);
106
107 // randomly adjust position of body[0]
108 const dReal *pos = dBodyGetPosition (body[0]);
109 dBodySetPosition (body[0],
110 pos[0]+0.2*(dRandReal()-0.5),
111 pos[1]+0.2*(dRandReal()-0.5),
112 pos[2]+0.2*(dRandReal()-0.5));
113 }
114 count++;
115 }
116
117 dWorldStep (world,0.05);
118 }
119
120 dReal sides1[3] = {SIDE,SIDE,SIDE};
121 dReal sides2[3] = {SIDE*0.8f,SIDE*0.8f,SIDE*2.0f};
122 dsSetTexture (DS_WOOD);
123 dsSetColor (1,1,0);
124 dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
125 dsSetColor (0,1,1);
126 dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
127}
128
129
130int main (int argc, char **argv)
131{
132 // setup pointers to drawstuff callback functions
133 dsFunctions fn;
134 fn.version = DS_VERSION;
135 fn.start = &start;
136 fn.step = &simLoop;
137 fn.command = &command;
138 fn.stop = 0;
139 fn.path_to_textures = "../../drawstuff/textures";
140 if(argc==2)
141 {
142 fn.path_to_textures = argv[1];
143 }
144
145 // create world
146 dInitODE();
147 world = dWorldCreate();
148 dMass m;
149 dMassSetBox (&m,1,SIDE,SIDE,SIDE);
150 dMassAdjust (&m,MASS);
151
152 body[0] = dBodyCreate (world);
153 dBodySetMass (body[0],&m);
154 dBodySetPosition (body[0],0,0,1);
155 body[1] = dBodyCreate (world);
156 dBodySetMass (body[1],&m);
157 dQuaternion q;
158 dQFromAxisAndAngle (q,-1,1,0,0.25*M_PI);
159 dBodySetPosition (body[1],0.2,0.2,1.2);
160 dBodySetQuaternion (body[1],q);
161
162 slider = dJointCreateSlider (world,0);
163 dJointAttach (slider,body[0],body[1]);
164 dJointSetSliderAxis (slider,1,1,1);
165
166 // run simulation
167 dsSimulationLoop (argc,argv,352,288,&fn);
168
169 dWorldDestroy (world);
170 dCloseODE();
171 return 0;
172}
diff --git a/libraries/ode-0.9/ode/demo/demo_space.cpp b/libraries/ode-0.9/ode/demo/demo_space.cpp
deleted file mode 100644
index 73101b5..0000000
--- a/libraries/ode-0.9/ode/demo/demo_space.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25testing procedure:
26 * create a bunch of random boxes
27 * test for intersections directly, put results in n^2 array
28 * get space to report collisions:
29 - all correct collisions reported
30 - no pair reported more than once
31 - no incorrect collisions reported
32
33*/
34
35
36#include <ode/ode.h>
37#include <drawstuff/drawstuff.h>
38
39#ifdef _MSC_VER
40#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
41#endif
42
43// select correct drawing functions
44
45#ifdef dDOUBLE
46#define dsDrawBox dsDrawBoxD
47#define dsDrawSphere dsDrawSphereD
48#define dsDrawCylinder dsDrawCylinderD
49#define dsDrawCapsule dsDrawCapsuleD
50#endif
51
52
53// some constants
54
55#define NUM 20 // number of boxes to test
56
57
58// collision objects and globals
59
60static dSpaceID space;
61static dGeomID geom[NUM];
62static dReal bounds[NUM][6];
63static size_t good_matrix[NUM][NUM]; // correct collision matrix
64static size_t test_matrix[NUM][NUM]; // testing collision matrix
65static size_t hits[NUM]; // number of collisions a box has
66static unsigned long seed=37;
67
68
69static void init_test()
70{
71 int i,j;
72 const dReal scale = 0.5;
73
74 // set random boxes
75 dRandSetSeed (seed);
76 for (i=0; i < NUM; i++) {
77 bounds[i][0] = dRandReal()*2-1;
78 bounds[i][1] = bounds[i][0] + dRandReal()*scale;
79 bounds[i][2] = dRandReal()*2-1;
80 bounds[i][3] = bounds[i][2] + dRandReal()*scale;
81 bounds[i][4] = dRandReal()*2;
82 bounds[i][5] = bounds[i][4] + dRandReal()*scale;
83
84 if (geom[i]) dGeomDestroy (geom[i]);
85 geom[i] = dCreateBox (space,
86 bounds[i][1] - bounds[i][0],
87 bounds[i][3] - bounds[i][2],
88 bounds[i][5] - bounds[i][4]);
89 dGeomSetPosition (geom[i],
90 (bounds[i][0] + bounds[i][1])*0.5,
91 (bounds[i][2] + bounds[i][3])*0.5,
92 (bounds[i][4] + bounds[i][5])*0.5);
93 dGeomSetData (geom[i],(void*)(size_t)(i));
94 }
95
96 // compute all intersections and put the results in "good_matrix"
97 for (i=0; i < NUM; i++) {
98 for (j=0; j < NUM; j++) good_matrix[i][j] = 0;
99 }
100 for (i=0; i < NUM; i++) hits[i] = 0;
101
102 for (i=0; i < NUM; i++) {
103 for (j=i+1; j < NUM; j++) {
104 dReal *bounds1 = &bounds[i][0];
105 dReal *bounds2 = &bounds[j][0];
106 if (bounds1[0] > bounds2[1] ||
107 bounds1[1] < bounds2[0] ||
108 bounds1[2] > bounds2[3] ||
109 bounds1[3] < bounds2[2] ||
110 bounds1[4] > bounds2[5] ||
111 bounds1[5] < bounds2[4]) continue;
112 good_matrix[i][j] = 1;
113 good_matrix[j][i] = 1;
114 hits[i]++;
115 hits[j]++;
116 }
117 }
118}
119
120
121// this is called by dSpaceCollide when two objects in space are
122// potentially colliding.
123
124static void nearCallback (void *data, dGeomID o1, dGeomID o2)
125{
126 size_t i,j;
127 i = (size_t) dGeomGetData (o1);
128 j = (size_t) dGeomGetData (o2);
129 if (i==j)
130 printf ("collision (%d,%d) is between the same object\n",i,j);
131 if (!good_matrix[i][j] || !good_matrix[j][i])
132 printf ("collision (%d,%d) is incorrect\n",i,j);
133 if (test_matrix[i][j] || test_matrix[j][i])
134 printf ("collision (%d,%d) reported more than once\n",i,j);
135 test_matrix[i][j] = 1;
136 test_matrix[j][i] = 1;
137}
138
139
140// start simulation - set viewpoint
141
142static void start()
143{
144 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
145 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
146 dsSetViewpoint (xyz,hpr);
147}
148
149
150static void command (int cmd)
151{
152 if (cmd == ' ') {
153 seed++;
154 init_test();
155 }
156}
157
158
159// simulation loop
160
161static void simLoop (int pause)
162{
163 int i,j;
164
165 for (i=0; i < NUM; i++) {
166 for (j=0; j < NUM; j++) test_matrix[i][j] = 0;
167 }
168 dSpaceCollide (space,0,&nearCallback);
169 for (i=0; i < NUM; i++) {
170 for (j=i+1; j < NUM; j++) {
171 if (good_matrix[i][j] && !test_matrix[i][j]) {
172 printf ("failed to report collision (%d,%d) (seed=%ld)\n",i,j,seed);
173 }
174 }
175 }
176
177 seed++;
178 init_test();
179
180 for (i=0; i<NUM; i++) {
181 dVector3 pos,side;
182 dMatrix3 R;
183 dRSetIdentity (R);
184 for (j=0; j<3; j++) pos[j] = (bounds[i][j*2+1] + bounds[i][j*2]) * 0.5;
185 for (j=0; j<3; j++) side[j] = bounds[i][j*2+1] - bounds[i][j*2];
186 if (hits[i] > 0) dsSetColor (1,0,0);
187 else dsSetColor (1,1,0);
188 dsDrawBox (pos,R,side);
189 }
190}
191
192
193int main (int argc, char **argv)
194{
195 int i;
196
197 // setup pointers to drawstuff callback functions
198 dsFunctions fn;
199 fn.version = DS_VERSION;
200 fn.start = &start;
201 fn.step = &simLoop;
202 fn.command = &command;
203 fn.stop = 0;
204 fn.path_to_textures = "../../drawstuff/textures";
205 if(argc==2)
206 {
207 fn.path_to_textures = argv[1];
208 }
209
210 dInitODE();
211
212 // test the simple space:
213 // space = dSimpleSpaceCreate();
214
215 // test the hash space:
216 // space = dHashSpaceCreate (0);
217 // dHashSpaceSetLevels (space,-10,10);
218
219 // test the quadtree space
220 dVector3 Center = {0, 0, 0, 0};
221 dVector3 Extents = {10, 0, 10, 0};
222 space = dQuadTreeSpaceCreate(0, Center, Extents, 7);
223
224 for (i=0; i < NUM; i++) geom[i] = 0;
225 init_test();
226
227 // run simulation
228 dsSimulationLoop (argc,argv,352,288,&fn);
229
230 dSpaceDestroy (space);
231 dCloseODE();
232 return 0;
233}
diff --git a/libraries/ode-0.9/ode/demo/demo_space_stress.cpp b/libraries/ode-0.9/ode/demo/demo_space_stress.cpp
deleted file mode 100644
index e1be369..0000000
--- a/libraries/ode-0.9/ode/demo/demo_space_stress.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/ode.h>
24#include <drawstuff/drawstuff.h>
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30// select correct drawing functions
31
32#ifdef dDOUBLE
33#define dsDrawBox dsDrawBoxD
34#define dsDrawSphere dsDrawSphereD
35#define dsDrawCylinder dsDrawCylinderD
36#define dsDrawCapsule dsDrawCapsuleD
37#endif
38
39
40// some constants
41
42#define NUM 10000 // max number of objects
43#define DENSITY (5.0) // density of all objects
44#define GPB 3 // maximum number of geometries per body
45#define MAX_CONTACTS 4 // maximum number of contact points per body
46#define WORLD_SIZE 100
47
48
49// dynamics and collision objects
50
51struct MyObject {
52 dBodyID body; // the body
53 dGeomID geom[GPB]; // geometries representing this body
54};
55
56static int num=0; // number of objects in simulation
57static int nextobj=0; // next object to recycle if num==NUM
58static dWorldID world;
59static dSpaceID space;
60static MyObject obj[NUM];
61static dJointGroupID contactgroup;
62static int selected = -1; // selected object
63static int show_aabb = 0; // show geom AABBs?
64static int show_contacts = 0; // show contact points?
65static int random_pos = 1; // drop objects from random position?
66static int draw_geom = 1;
67
68
69// this is called by dSpaceCollide when two objects in space are
70// potentially colliding.
71
72static void nearCallback (void *data, dGeomID o1, dGeomID o2)
73{
74 int i;
75 // if (o1->body && o2->body) return;
76
77 // exit without doing anything if the two bodies are connected by a joint
78 dBodyID b1 = dGeomGetBody(o1);
79 dBodyID b2 = dGeomGetBody(o2);
80 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
81
82 dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
83 for (i=0; i<MAX_CONTACTS; i++) {
84 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
85 contact[i].surface.mu = dInfinity;
86 contact[i].surface.mu2 = 0;
87 contact[i].surface.bounce = 0.1;
88 contact[i].surface.bounce_vel = 0.1;
89 contact[i].surface.soft_cfm = 0.01;
90 }
91 if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
92 sizeof(dContact))) {
93 dMatrix3 RI;
94 dRSetIdentity (RI);
95 const dReal ss[3] = {0.02,0.02,0.02};
96 for (i=0; i<numc; i++) {
97 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
98 dJointAttach (c,b1,b2);
99 if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
100 }
101 }
102}
103
104
105// start simulation - set viewpoint
106
107static void start()
108{
109 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
110 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
111 dsSetViewpoint (xyz,hpr);
112 printf ("To drop another object, press:\n");
113 printf (" o to disable rendering.\n");
114 printf (" b for box.\n");
115 printf (" s for sphere.\n");
116 printf (" c for cylinder.\n");
117 printf (" x for a composite object.\n");
118 printf ("To select an object, press space.\n");
119 printf ("To disable the selected object, press d.\n");
120 printf ("To enable the selected object, press e.\n");
121 printf ("To toggle showing the geom AABBs, press a.\n");
122 printf ("To toggle showing the contact points, press t.\n");
123 printf ("To toggle dropping from random position/orientation, press r.\n");
124}
125
126
127char locase (char c)
128{
129 if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
130 else return c;
131}
132
133
134// called when a key pressed
135
136static void command (int cmd)
137{
138 int i,j,k;
139 dReal sides[3];
140 dMass m;
141
142 cmd = locase (cmd);
143 if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
144 /* || cmd == 'l' */) {
145 if (num < NUM) {
146 i = num;
147 num++;
148 }
149 else {
150 i = nextobj;
151 nextobj++;
152 if (nextobj >= num) nextobj = 0;
153
154 // destroy the body and geoms for slot i
155 dBodyDestroy (obj[i].body);
156 for (k=0; k < GPB; k++) {
157 if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
158 }
159 memset (&obj[i],0,sizeof(obj[i]));
160 }
161
162 obj[i].body = dBodyCreate (world);
163 for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
164
165 dMatrix3 R;
166 if (random_pos) {
167 dBodySetPosition (obj[i].body,
168 dRandReal()*WORLD_SIZE-(WORLD_SIZE/2),dRandReal()*WORLD_SIZE-(WORLD_SIZE/2),dRandReal()+1);
169 dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
170 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
171 }
172 else {
173 dReal maxheight = 0;
174 for (k=0; k<num; k++) {
175 const dReal *pos = dBodyGetPosition (obj[k].body);
176 if (pos[2] > maxheight) maxheight = pos[2];
177 }
178 dBodySetPosition (obj[i].body, 0,0,maxheight+1);
179 dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
180 }
181 dBodySetRotation (obj[i].body,R);
182 dBodySetData (obj[i].body,(void*)(size_t)i);
183
184 if (cmd == 'b') {
185 dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
186 obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
187 }
188 else if (cmd == 'c') {
189 sides[0] *= 0.5;
190 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
191 obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
192 }
193/*
194 // cylinder option not yet implemented
195 else if (cmd == 'l') {
196 sides[1] *= 0.5;
197 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
198 obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
199 }
200*/
201 else if (cmd == 's') {
202 sides[0] *= 0.5;
203 dMassSetSphere (&m,DENSITY,sides[0]);
204 obj[i].geom[0] = dCreateSphere (space,sides[0]);
205 }
206 else if (cmd == 'x') {
207 dGeomID g2[GPB]; // encapsulated geometries
208 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
209
210 // start accumulating masses for the encapsulated geometries
211 dMass m2;
212 dMassSetZero (&m);
213
214 // set random delta positions
215 for (j=0; j<GPB; j++) {
216 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
217 }
218
219 for (k=0; k<GPB; k++) {
220 obj[i].geom[k] = dCreateGeomTransform (space);
221 dGeomTransformSetCleanup (obj[i].geom[k],1);
222 if (k==0) {
223 dReal radius = dRandReal()*0.25+0.05;
224 g2[k] = dCreateSphere (0,radius);
225 dMassSetSphere (&m2,DENSITY,radius);
226 }
227 else if (k==1) {
228 g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
229 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
230 }
231 else {
232 dReal radius = dRandReal()*0.1+0.05;
233 dReal length = dRandReal()*1.0+0.1;
234 g2[k] = dCreateCapsule (0,radius,length);
235 dMassSetCapsule (&m2,DENSITY,3,radius,length);
236 }
237 dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
238
239 // set the transformation (adjust the mass too)
240 dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
241 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
242 dMatrix3 Rtx;
243 dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
244 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
245 dGeomSetRotation (g2[k],Rtx);
246 dMassRotate (&m2,Rtx);
247
248 // add to the total mass
249 dMassAdd (&m,&m2);
250 }
251
252 // move all encapsulated objects so that the center of mass is (0,0,0)
253 for (k=0; k<2; k++) {
254 dGeomSetPosition (g2[k],
255 dpos[k][0]-m.c[0],
256 dpos[k][1]-m.c[1],
257 dpos[k][2]-m.c[2]);
258 }
259 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
260 }
261
262 for (k=0; k < GPB; k++) {
263 if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
264 }
265
266 dBodySetMass (obj[i].body,&m);
267 }
268
269 if (cmd == ' ') {
270 selected++;
271 if (selected >= num) selected = 0;
272 if (selected < 0) selected = 0;
273 }
274 else if (cmd == 'd' && selected >= 0 && selected < num) {
275 dBodyDisable (obj[selected].body);
276 }
277 else if (cmd == 'e' && selected >= 0 && selected < num) {
278 dBodyEnable (obj[selected].body);
279 }
280 else if (cmd == 'a') {
281 show_aabb ^= 1;
282 }
283 else if (cmd == 't') {
284 show_contacts ^= 1;
285 }
286 else if (cmd == 'r') {
287 random_pos ^= 1;
288 }
289 else if (cmd == 'o') {
290 draw_geom ^= 1;
291 }
292}
293
294
295// draw a geom
296
297void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
298{
299 if (!draw_geom){
300 return;
301 }
302
303 if (!g) return;
304 if (!pos) pos = dGeomGetPosition (g);
305 if (!R) R = dGeomGetRotation (g);
306
307 int type = dGeomGetClass (g);
308 if (type == dBoxClass) {
309 dVector3 sides;
310 dGeomBoxGetLengths (g,sides);
311 dsDrawBox (pos,R,sides);
312 }
313 else if (type == dSphereClass) {
314 dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
315 }
316 else if (type == dCapsuleClass) {
317 dReal radius,length;
318 dGeomCapsuleGetParams (g,&radius,&length);
319 dsDrawCapsule (pos,R,length,radius);
320 }
321/*
322 // cylinder option not yet implemented
323 else if (type == dCylinderClass) {
324 dReal radius,length;
325 dGeomCylinderGetParams (g,&radius,&length);
326 dsDrawCylinder (pos,R,length,radius);
327 }
328*/
329 else if (type == dGeomTransformClass) {
330 dGeomID g2 = dGeomTransformGetGeom (g);
331 const dReal *pos2 = dGeomGetPosition (g2);
332 const dReal *R2 = dGeomGetRotation (g2);
333 dVector3 actual_pos;
334 dMatrix3 actual_R;
335 dMULTIPLY0_331 (actual_pos,R,pos2);
336 actual_pos[0] += pos[0];
337 actual_pos[1] += pos[1];
338 actual_pos[2] += pos[2];
339 dMULTIPLY0_333 (actual_R,R,R2);
340 drawGeom (g2,actual_pos,actual_R,0);
341 }
342
343 if (show_aabb) {
344 // draw the bounding box for this geom
345 dReal aabb[6];
346 dGeomGetAABB (g,aabb);
347 dVector3 bbpos;
348 for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
349 dVector3 bbsides;
350 for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
351 dMatrix3 RI;
352 dRSetIdentity (RI);
353 dsSetColorAlpha (1,0,0,0.5);
354 dsDrawBox (bbpos,RI,bbsides);
355 }
356}
357
358
359// simulation loop
360
361static void simLoop (int pause)
362{
363 dsSetColor (0,0,2);
364 dSpaceCollide (space,0,&nearCallback);
365 //if (!pause) dWorldStep (world,0.05);
366 //if (!pause) dWorldStepFast (world,0.05, 1);
367
368 // remove all contact joints
369 dJointGroupEmpty (contactgroup);
370
371 dsSetColor (1,1,0);
372 dsSetTexture (DS_WOOD);
373 for (int i=0; i<num; i++) {
374 for (int j=0; j < GPB; j++) {
375 if (i==selected) {
376 dsSetColor (0,0.7,1);
377 }
378 else if (! dBodyIsEnabled (obj[i].body)) {
379 dsSetColor (1,0,0);
380 }
381 else {
382 dsSetColor (1,1,0);
383 }
384 drawGeom (obj[i].geom[j],0,0,show_aabb);
385 }
386 }
387}
388
389
390int main (int argc, char **argv)
391{
392 // setup pointers to drawstuff callback functions
393 dsFunctions fn;
394 fn.version = DS_VERSION;
395 fn.start = &start;
396 fn.step = &simLoop;
397 fn.command = &command;
398 fn.stop = 0;
399 fn.path_to_textures = "../../drawstuff/textures";
400 if(argc==2)
401 {
402 fn.path_to_textures = argv[1];
403 }
404
405 // create world
406 dInitODE();
407 world = dWorldCreate();
408
409
410 dVector3 Center = {0, 0, 0, 0};
411 dVector3 Extents = {WORLD_SIZE * 0.55, WORLD_SIZE * 0.55, WORLD_SIZE * 0.55, 0};
412
413 //space = dSimpleSpaceCreate(0);
414 //space = dHashSpaceCreate (0);
415 space = dQuadTreeSpaceCreate (0, Center, Extents, 6);
416
417 contactgroup = dJointGroupCreate (0);
418 dWorldSetGravity (world,0,0,-0.5);
419 dWorldSetCFM (world,1e-5);
420 dCreatePlane (space,0,0,1,0);
421 memset (obj,0,sizeof(obj));
422
423 for (int i = 0; i < NUM; i++){
424 command('s');
425 }
426
427 // run simulation
428 dsSimulationLoop (argc,argv,352,288,&fn);
429
430 dJointGroupDestroy (contactgroup);
431 dSpaceDestroy (space);
432 dWorldDestroy (world);
433 dCloseODE();
434 return 0;
435}
diff --git a/libraries/ode-0.9/ode/demo/demo_step.cpp b/libraries/ode-0.9/ode/demo/demo_step.cpp
deleted file mode 100644
index df2385c..0000000
--- a/libraries/ode-0.9/ode/demo/demo_step.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// test the step function by comparing the output of the fast and the slow
24// version, for various systems. currently you have to define COMPARE_METHODS
25// in step.cpp for this to work properly.
26//
27// @@@ report MAX error
28
29#include <time.h>
30#include <ode/ode.h>
31#include <drawstuff/drawstuff.h>
32
33#ifdef _MSC_VER
34#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
35#endif
36
37// select correct drawing functions
38
39#ifdef dDOUBLE
40#define dsDrawBox dsDrawBoxD
41#define dsDrawSphere dsDrawSphereD
42#define dsDrawCylinder dsDrawCylinderD
43#define dsDrawCapsule dsDrawCapsuleD
44#endif
45
46
47// some constants
48
49#define NUM 10 // number of bodies
50#define NUMJ 9 // number of joints
51#define SIDE (0.2) // side length of a box
52#define MASS (1.0) // mass of a box
53#define RADIUS (0.1732f) // sphere radius
54
55
56
57// dynamics and collision objects
58
59static dWorldID world=0;
60static dBodyID body[NUM];
61static dJointID joint[NUMJ];
62
63
64// create the test system
65
66void createTest()
67{
68 int i,j;
69 if (world) dWorldDestroy (world);
70
71 world = dWorldCreate();
72
73 // create random bodies
74 for (i=0; i<NUM; i++) {
75 // create bodies at random position and orientation
76 body[i] = dBodyCreate (world);
77 dBodySetPosition (body[i],dRandReal()*2-1,dRandReal()*2-1,
78 dRandReal()*2+RADIUS);
79 dReal q[4];
80 for (j=0; j<4; j++) q[j] = dRandReal()*2-1;
81 dBodySetQuaternion (body[i],q);
82
83 // set random velocity
84 dBodySetLinearVel (body[i], dRandReal()*2-1,dRandReal()*2-1,
85 dRandReal()*2-1);
86 dBodySetAngularVel (body[i], dRandReal()*2-1,dRandReal()*2-1,
87 dRandReal()*2-1);
88
89 // set random mass (random diagonal mass rotated by a random amount)
90 dMass m;
91 dMatrix3 R;
92 dMassSetBox (&m,1,dRandReal()+0.1,dRandReal()+0.1,dRandReal()+0.1);
93 dMassAdjust (&m,dRandReal()+1);
94 for (j=0; j<4; j++) q[j] = dRandReal()*2-1;
95 dQtoR (q,R);
96 dMassRotate (&m,R);
97 dBodySetMass (body[i],&m);
98 }
99
100 // create ball-n-socket joints at random positions, linking random bodies
101 // (but make sure not to link the same pair of bodies twice)
102 char linked[NUM*NUM];
103 for (i=0; i<NUM*NUM; i++) linked[i] = 0;
104 for (i=0; i<NUMJ; i++) {
105 int b1,b2;
106 do {
107 b1 = dRandInt (NUM);
108 b2 = dRandInt (NUM);
109 } while (linked[b1*NUM + b2] || b1==b2);
110 linked[b1*NUM + b2] = 1;
111 linked[b2*NUM + b1] = 1;
112 joint[i] = dJointCreateBall (world,0);
113 dJointAttach (joint[i],body[b1],body[b2]);
114 dJointSetBallAnchor (joint[i],dRandReal()*2-1,
115 dRandReal()*2-1,dRandReal()*2+RADIUS);
116 }
117
118 for (i=0; i<NUM; i++) {
119 // move bodies a bit to get some joint error
120 const dReal *pos = dBodyGetPosition (body[i]);
121 dBodySetPosition (body[i],pos[0]+dRandReal()*0.2-0.1,
122 pos[1]+dRandReal()*0.2-0.1,pos[2]+dRandReal()*0.2-0.1);
123 }
124}
125
126
127// start simulation - set viewpoint
128
129static void start()
130{
131 static float xyz[3] = {2.6117f,-1.4433f,2.3700f};
132 static float hpr[3] = {151.5000f,-30.5000f,0.0000f};
133 dsSetViewpoint (xyz,hpr);
134}
135
136
137// simulation loop
138
139static void simLoop (int pause)
140{
141 if (!pause) {
142 // add random forces and torques to all bodies
143 int i;
144 const dReal scale1 = 5;
145 const dReal scale2 = 5;
146 for (i=0; i<NUM; i++) {
147 dBodyAddForce (body[i],
148 scale1*(dRandReal()*2-1),
149 scale1*(dRandReal()*2-1),
150 scale1*(dRandReal()*2-1));
151 dBodyAddTorque (body[i],
152 scale2*(dRandReal()*2-1),
153 scale2*(dRandReal()*2-1),
154 scale2*(dRandReal()*2-1));
155 }
156
157 dWorldStep (world,0.05);
158 createTest();
159 }
160
161 // float sides[3] = {SIDE,SIDE,SIDE};
162 dsSetColor (1,1,0);
163 for (int i=0; i<NUM; i++)
164 dsDrawSphere (dBodyGetPosition(body[i]), dBodyGetRotation(body[i]),RADIUS);
165}
166
167
168int main (int argc, char **argv)
169{
170 // setup pointers to drawstuff callback functions
171 dsFunctions fn;
172 fn.version = DS_VERSION;
173 fn.start = &start;
174 fn.step = &simLoop;
175 fn.command = 0;
176 fn.stop = 0;
177 fn.path_to_textures = "../../drawstuff/textures";
178 if(argc==2)
179 {
180 fn.path_to_textures = argv[1];
181 }
182
183 dInitODE();
184 dRandSetSeed (time(0));
185 createTest();
186
187 // run simulation
188 dsSimulationLoop (argc,argv,352,288,&fn);
189
190 dWorldDestroy (world);
191 dCloseODE();
192 return 0;
193}
diff --git a/libraries/ode-0.9/ode/demo/demo_trimesh.cpp b/libraries/ode-0.9/ode/demo/demo_trimesh.cpp
deleted file mode 100644
index f87ff0b..0000000
--- a/libraries/ode-0.9/ode/demo/demo_trimesh.cpp
+++ /dev/null
@@ -1,537 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh test by Erwin de Vries
24
25#include <ode/ode.h>
26#include <drawstuff/drawstuff.h>
27
28#ifdef _MSC_VER
29#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
30#endif
31
32// select correct drawing functions
33
34#ifdef dDOUBLE
35#define dsDrawBox dsDrawBoxD
36#define dsDrawSphere dsDrawSphereD
37#define dsDrawCylinder dsDrawCylinderD
38#define dsDrawCapsule dsDrawCapsuleD
39#define dsDrawLine dsDrawLineD
40#define dsDrawTriangle dsDrawTriangleD
41#endif
42
43
44// some constants
45
46#define NUM 200 // max number of objects
47#define DENSITY (5.0) // density of all objects
48#define GPB 3 // maximum number of geometries per body
49#define MAX_CONTACTS 40 // maximum number of contact points per body
50
51
52// dynamics and collision objects
53
54struct MyObject {
55 dBodyID body; // the body
56 dGeomID geom[GPB]; // geometries representing this body
57};
58
59static int num=0; // number of objects in simulation
60static int nextobj=0; // next object to recycle if num==NUM
61static dWorldID world;
62static dSpaceID space;
63static MyObject obj[NUM];
64static dJointGroupID contactgroup;
65static int selected = -1; // selected object
66static int show_aabb = 0; // show geom AABBs?
67static int show_contacts = 0; // show contact points?
68static int random_pos = 1; // drop objects from random position?
69
70#define VertexCount 5
71#define IndexCount 12
72
73static dVector3 Size;
74static dVector3 Vertices[VertexCount];
75static int Indices[IndexCount];
76
77static dGeomID TriMesh;
78static dGeomID Ray;
79
80
81// this is called by dSpaceCollide when two objects in space are
82// potentially colliding.
83
84static void nearCallback (void *data, dGeomID o1, dGeomID o2)
85{
86 int i;
87 // if (o1->body && o2->body) return;
88
89 // exit without doing anything if the two bodies are connected by a joint
90 dBodyID b1 = dGeomGetBody(o1);
91 dBodyID b2 = dGeomGetBody(o2);
92 if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
93
94 dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
95 for (i=0; i<MAX_CONTACTS; i++) {
96 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
97 contact[i].surface.mu = dInfinity;
98 contact[i].surface.mu2 = 0;
99 contact[i].surface.bounce = 0.1;
100 contact[i].surface.bounce_vel = 0.1;
101 contact[i].surface.soft_cfm = 0.01;
102 }
103 if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
104 sizeof(dContact))) {
105 dMatrix3 RI;
106 dRSetIdentity (RI);
107 const dReal ss[3] = {0.02,0.02,0.02};
108 for (i=0; i<numc; i++) {
109 if (dGeomGetClass(o1) == dRayClass || dGeomGetClass(o2) == dRayClass){
110 dMatrix3 Rotation;
111 dRSetIdentity(Rotation);
112 dsDrawSphere(contact[i].geom.pos, Rotation, REAL(0.01));
113
114 dVector3 End;
115 End[0] = contact[i].geom.pos[0] + (contact[i].geom.normal[0] * contact[i].geom.depth);
116 End[1] = contact[i].geom.pos[1] + (contact[i].geom.normal[1] * contact[i].geom.depth);
117 End[2] = contact[i].geom.pos[2] + (contact[i].geom.normal[2] * contact[i].geom.depth);
118 End[3] = contact[i].geom.pos[3] + (contact[i].geom.normal[3] * contact[i].geom.depth);
119
120 dsDrawLine(contact[i].geom.pos, End);
121 continue;
122 }
123
124 dJointID c = dJointCreateContact (world,contactgroup,contact+i);
125 dJointAttach (c,b1,b2);
126 if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
127 }
128 }
129}
130
131
132// start simulation - set viewpoint
133
134static void start()
135{
136 static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
137 static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
138 dsSetViewpoint (xyz,hpr);
139 printf ("To drop another object, press:\n");
140 printf (" b for box.\n");
141 printf (" s for sphere.\n");
142 printf (" c for cylinder.\n");
143 printf (" x for a composite object.\n");
144 printf ("To select an object, press space.\n");
145 printf ("To disable the selected object, press d.\n");
146 printf ("To enable the selected object, press e.\n");
147 printf ("To toggle showing the geom AABBs, press a.\n");
148 printf ("To toggle showing the contact points, press t.\n");
149 printf ("To toggle dropping from random position/orientation, press r.\n");
150}
151
152
153char locase (char c)
154{
155 if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
156 else return c;
157}
158
159
160// called when a key pressed
161
162static void command (int cmd)
163{
164 int i,j,k;
165 dReal sides[3];
166 dMass m;
167
168 cmd = locase (cmd);
169 if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
170 /* || cmd == 'l' */) {
171 if (num < NUM) {
172 i = num;
173 num++;
174 }
175 else {
176 i = nextobj;
177 nextobj++;
178 if (nextobj >= num) nextobj = 0;
179
180 // destroy the body and geoms for slot i
181 dBodyDestroy (obj[i].body);
182 for (k=0; k < GPB; k++) {
183 if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
184 }
185 memset (&obj[i],0,sizeof(obj[i]));
186 }
187
188 obj[i].body = dBodyCreate (world);
189 for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
190
191 dMatrix3 R;
192 if (random_pos) {
193 dBodySetPosition (obj[i].body,
194 dRandReal()*2-1,dRandReal()*2-1,dRandReal()+1);
195 dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
196 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
197 }
198 else {
199 dReal maxheight = 0;
200 for (k=0; k<num; k++) {
201 const dReal *pos = dBodyGetPosition (obj[k].body);
202 if (pos[2] > maxheight) maxheight = pos[2];
203 }
204 dBodySetPosition (obj[i].body, 0,0,maxheight+1);
205 dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
206 }
207 dBodySetRotation (obj[i].body,R);
208 dBodySetData (obj[i].body,(void*)(size_t)i);
209
210 if (cmd == 'b') {
211 dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
212 obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
213 }
214 else if (cmd == 'c') {
215 sides[0] *= 0.5;
216 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
217 obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
218 }
219/*
220 // cylinder option not yet implemented
221 else if (cmd == 'l') {
222 sides[1] *= 0.5;
223 dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
224 obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
225 }
226*/
227 else if (cmd == 's') {
228 sides[0] *= 0.5;
229 dMassSetSphere (&m,DENSITY,sides[0]);
230 obj[i].geom[0] = dCreateSphere (space,sides[0]);
231 }
232 else if (cmd == 'x') {
233 dGeomID g2[GPB]; // encapsulated geometries
234 dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
235
236 // start accumulating masses for the encapsulated geometries
237 dMass m2;
238 dMassSetZero (&m);
239
240 // set random delta positions
241 for (j=0; j<GPB; j++) {
242 for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
243 }
244
245 for (k=0; k<GPB; k++) {
246 obj[i].geom[k] = dCreateGeomTransform (space);
247 dGeomTransformSetCleanup (obj[i].geom[k],1);
248 if (k==0) {
249 dReal radius = dRandReal()*0.25+0.05;
250 g2[k] = dCreateSphere (0,radius);
251 dMassSetSphere (&m2,DENSITY,radius);
252 }
253 else if (k==1) {
254 g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
255 dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
256 }
257 else {
258 dReal radius = dRandReal()*0.1+0.05;
259 dReal length = dRandReal()*1.0+0.1;
260 g2[k] = dCreateCapsule (0,radius,length);
261 dMassSetCapsule (&m2,DENSITY,3,radius,length);
262 }
263 dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
264
265 // set the transformation (adjust the mass too)
266 dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
267 dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
268 dMatrix3 Rtx;
269 dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
270 dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
271 dGeomSetRotation (g2[k],Rtx);
272 dMassRotate (&m2,Rtx);
273
274 // add to the total mass
275 dMassAdd (&m,&m2);
276 }
277
278 // move all encapsulated objects so that the center of mass is (0,0,0)
279 for (k=0; k<2; k++) {
280 dGeomSetPosition (g2[k],
281 dpos[k][0]-m.c[0],
282 dpos[k][1]-m.c[1],
283 dpos[k][2]-m.c[2]);
284 }
285 dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
286 }
287
288 for (k=0; k < GPB; k++) {
289 if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
290 }
291
292 dBodySetMass (obj[i].body,&m);
293 }
294
295 if (cmd == ' ') {
296 selected++;
297 if (selected >= num) selected = 0;
298 if (selected < 0) selected = 0;
299 }
300 else if (cmd == 'd' && selected >= 0 && selected < num) {
301 dBodyDisable (obj[selected].body);
302 }
303 else if (cmd == 'e' && selected >= 0 && selected < num) {
304 dBodyEnable (obj[selected].body);
305 }
306 else if (cmd == 'a') {
307 show_aabb ^= 1;
308 }
309 else if (cmd == 't') {
310 show_contacts ^= 1;
311 }
312 else if (cmd == 'r') {
313 random_pos ^= 1;
314 }
315}
316
317
318// draw a geom
319
320void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
321{
322 if (!g) return;
323 if (!pos) pos = dGeomGetPosition (g);
324 if (!R) R = dGeomGetRotation (g);
325
326 int type = dGeomGetClass (g);
327 if (type == dBoxClass) {
328 dVector3 sides;
329 dGeomBoxGetLengths (g,sides);
330 dsDrawBox (pos,R,sides);
331 }
332 else if (type == dSphereClass) {
333 dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
334 }
335 else if (type == dCapsuleClass) {
336 dReal radius,length;
337 dGeomCapsuleGetParams (g,&radius,&length);
338 dsDrawCapsule (pos,R,length,radius);
339 }
340/*
341 // cylinder option not yet implemented
342 else if (type == dCylinderClass) {
343 dReal radius,length;
344 dGeomCylinderGetParams (g,&radius,&length);
345 dsDrawCylinder (pos,R,length,radius);
346 }
347*/
348 else if (type == dGeomTransformClass) {
349 dGeomID g2 = dGeomTransformGetGeom (g);
350 const dReal *pos2 = dGeomGetPosition (g2);
351 const dReal *R2 = dGeomGetRotation (g2);
352 dVector3 actual_pos;
353 dMatrix3 actual_R;
354 dMULTIPLY0_331 (actual_pos,R,pos2);
355 actual_pos[0] += pos[0];
356 actual_pos[1] += pos[1];
357 actual_pos[2] += pos[2];
358 dMULTIPLY0_333 (actual_R,R,R2);
359 drawGeom (g2,actual_pos,actual_R,0);
360 }
361
362 if (show_aabb) {
363 // draw the bounding box for this geom
364 dReal aabb[6];
365 dGeomGetAABB (g,aabb);
366 dVector3 bbpos;
367 for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
368 dVector3 bbsides;
369 for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
370 dMatrix3 RI;
371 dRSetIdentity (RI);
372 dsSetColorAlpha (1,0,0,0.5);
373 dsDrawBox (bbpos,RI,bbsides);
374 }
375}
376
377
378// simulation loop
379
380static void simLoop (int pause)
381{
382 dsSetColor (0,0,2);
383 dSpaceCollide (space,0,&nearCallback);
384 if (!pause) dWorldStep (world,0.05);
385 //if (!pause) dWorldStepFast (world,0.05, 1);
386
387 // remove all contact joints
388 dJointGroupEmpty (contactgroup);
389
390 dsSetColor (1,1,0);
391 dsSetTexture (DS_WOOD);
392 for (int i=0; i<num; i++) {
393 for (int j=0; j < GPB; j++) {
394 if (i==selected) {
395 dsSetColor (0,0.7,1);
396 }
397 else if (! dBodyIsEnabled (obj[i].body)) {
398 dsSetColor (1,0,0);
399 }
400 else {
401 dsSetColor (1,1,0);
402 }
403 drawGeom (obj[i].geom[j],0,0,show_aabb);
404 }
405 }
406
407 /*{
408 for (int i = 1; i < IndexCount; i++) {
409 dsDrawLine(Vertices[Indices[i - 1]], Vertices[Indices[i]]);
410 }
411 }*/
412
413 {const dReal* Pos = dGeomGetPosition(TriMesh);
414 const dReal* Rot = dGeomGetRotation(TriMesh);
415
416 {for (int i = 0; i < IndexCount / 3; i++){
417 const dVector3& v0 = Vertices[Indices[i * 3 + 0]];
418 const dVector3& v1 = Vertices[Indices[i * 3 + 1]];
419 const dVector3& v2 = Vertices[Indices[i * 3 + 2]];
420 dsDrawTriangle(Pos, Rot, (dReal*)&v0, (dReal*)&v1, (dReal*)&v2, 0);
421 }}}
422
423 if (Ray){
424 dVector3 Origin, Direction;
425 dGeomRayGet(Ray, Origin, Direction);
426
427 dReal Length = dGeomRayGetLength(Ray);
428
429 dVector3 End;
430 End[0] = Origin[0] + (Direction[0] * Length);
431 End[1] = Origin[1] + (Direction[1] * Length);
432 End[2] = Origin[2] + (Direction[2] * Length);
433 End[3] = Origin[3] + (Direction[3] * Length);
434
435 dsDrawLine(Origin, End);
436 }
437}
438
439
440int main (int argc, char **argv)
441{
442 // setup pointers to drawstuff callback functions
443 dsFunctions fn;
444 fn.version = DS_VERSION;
445 fn.start = &start;
446 fn.step = &simLoop;
447 fn.command = &command;
448 fn.stop = 0;
449 fn.path_to_textures = "../../drawstuff/textures";
450 if(argc==2)
451 {
452 fn.path_to_textures = argv[1];
453 }
454
455 // create world
456 dInitODE();
457 world = dWorldCreate();
458
459 space = dSimpleSpaceCreate(0);
460 contactgroup = dJointGroupCreate (0);
461 dWorldSetGravity (world,0,0,-0.5);
462 dWorldSetCFM (world,1e-5);
463 //dCreatePlane (space,0,0,1,0);
464 memset (obj,0,sizeof(obj));
465
466 Size[0] = 5.0f;
467 Size[1] = 5.0f;
468 Size[2] = 2.5f;
469
470 Vertices[0][0] = -Size[0];
471 Vertices[0][1] = -Size[1];
472 Vertices[0][2] = Size[2];
473
474 Vertices[1][0] = Size[0];
475 Vertices[1][1] = -Size[1];
476 Vertices[1][2] = Size[2];
477
478 Vertices[2][0] = Size[0];
479 Vertices[2][1] = Size[1];
480 Vertices[2][2] = Size[2];
481
482 Vertices[3][0] = -Size[0];
483 Vertices[3][1] = Size[1];
484 Vertices[3][2] = Size[2];
485
486 Vertices[4][0] = 0;
487 Vertices[4][1] = 0;
488 Vertices[4][2] = 0;
489
490 Indices[0] = 0;
491 Indices[1] = 1;
492 Indices[2] = 4;
493
494 Indices[3] = 1;
495 Indices[4] = 2;
496 Indices[5] = 4;
497
498 Indices[6] = 2;
499 Indices[7] = 3;
500 Indices[8] = 4;
501
502 Indices[9] = 3;
503 Indices[10] = 0;
504 Indices[11] = 4;
505
506 dTriMeshDataID Data = dGeomTriMeshDataCreate();
507
508 dGeomTriMeshDataBuildSimple(Data, (dReal*)Vertices, VertexCount, Indices, IndexCount);
509
510 TriMesh = dCreateTriMesh(space, Data, 0, 0, 0);
511
512 //dGeomSetPosition(TriMesh, 0, 0, 1.0);
513
514 Ray = dCreateRay(space, 0.9);
515 dVector3 Origin, Direction;
516 Origin[0] = 0.0;
517 Origin[1] = 0;
518 Origin[2] = 0.5;
519 Origin[3] = 0;
520
521 Direction[0] = 0;
522 Direction[1] = 1.1f;
523 Direction[2] = -1;
524 Direction[3] = 0;
525 dNormalize3(Direction);
526
527 dGeomRaySet(Ray, Origin[0], Origin[1], Origin[2], Direction[0], Direction[1], Direction[2]);
528
529 // run simulation
530 dsSimulationLoop (argc,argv,352,288,&fn);
531
532 dJointGroupDestroy (contactgroup);
533 dSpaceDestroy (space);
534 dWorldDestroy (world);
535 dCloseODE();
536 return 0;
537}
diff --git a/libraries/ode-0.9/ode/demo/world_geom3.h b/libraries/ode-0.9/ode/demo/world_geom3.h
deleted file mode 100644
index 0b94a5e..0000000
--- a/libraries/ode-0.9/ode/demo/world_geom3.h
+++ /dev/null
@@ -1,9 +0,0 @@
1// mesh for a world model, to be used with test_cyl.cpp
2
3static 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};
4
5static 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};
6
7
8static 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};
9
diff --git a/libraries/ode-0.9/ode/doc/Doxyfile b/libraries/ode-0.9/ode/doc/Doxyfile
deleted file mode 100644
index cd0b1d7..0000000
--- a/libraries/ode-0.9/ode/doc/Doxyfile
+++ /dev/null
@@ -1,1237 +0,0 @@
1# Doxyfile 1.4.6-NO
2
3# This file describes the settings to be used by the documentation system
4# doxygen (www.doxygen.org) for a project
5#
6# All text after a hash (#) is considered a comment and will be ignored
7# The format is:
8# TAG = value [value, ...]
9# For lists items can also be appended using:
10# TAG += value [value, ...]
11# Values that contain spaces should be placed between quotes (" ")
12
13#---------------------------------------------------------------------------
14# Project related configuration options
15#---------------------------------------------------------------------------
16
17# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
18# by quotes) that should identify the project.
19
20PROJECT_NAME = "Open Dynamics Engine"
21
22# The PROJECT_NUMBER tag can be used to enter a project or revision number.
23# This could be handy for archiving the generated documentation or
24# if some version control system is used.
25
26PROJECT_NUMBER =
27
28# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
29# base path where the generated documentation will be put.
30# If a relative path is entered, it will be relative to the location
31# where doxygen was started. If left blank the current directory will be used.
32
33OUTPUT_DIRECTORY = ../../docs
34
35# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
36# 4096 sub-directories (in 2 levels) under the output directory of each output
37# format and will distribute the generated files over these directories.
38# Enabling this option can be useful when feeding doxygen a huge amount of
39# source files, where putting all generated files in the same directory would
40# otherwise cause performance problems for the file system.
41
42CREATE_SUBDIRS = NO
43
44# The OUTPUT_LANGUAGE tag is used to specify the language in which all
45# documentation generated by doxygen is written. Doxygen will use this
46# information to generate all constant output in the proper language.
47# The default language is English, other supported languages are:
48# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
49# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
50# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
51# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
52# Swedish, and Ukrainian.
53
54OUTPUT_LANGUAGE = English
55
56# This tag can be used to specify the encoding used in the generated output.
57# The encoding is not always determined by the language that is chosen,
58# but also whether or not the output is meant for Windows or non-Windows users.
59# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
60# forces the Windows encoding (this is the default for the Windows binary),
61# whereas setting the tag to NO uses a Unix-style encoding (the default for
62# all platforms other than Windows).
63
64USE_WINDOWS_ENCODING = YES
65
66# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
67# include brief member descriptions after the members that are listed in
68# the file and class documentation (similar to JavaDoc).
69# Set to NO to disable this.
70
71BRIEF_MEMBER_DESC = YES
72
73# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
74# the brief description of a member or function before the detailed description.
75# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
76# brief descriptions will be completely suppressed.
77
78REPEAT_BRIEF = YES
79
80# This tag implements a quasi-intelligent brief description abbreviator
81# that is used to form the text in various listings. Each string
82# in this list, if found as the leading text of the brief description, will be
83# stripped from the text and the result after processing the whole list, is
84# used as the annotated text. Otherwise, the brief description is used as-is.
85# If left blank, the following values are used ("$name" is automatically
86# replaced with the name of the entity): "The $name class" "The $name widget"
87# "The $name file" "is" "provides" "specifies" "contains"
88# "represents" "a" "an" "the"
89
90ABBREVIATE_BRIEF =
91
92# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
93# Doxygen will generate a detailed section even if there is only a brief
94# description.
95
96ALWAYS_DETAILED_SEC = NO
97
98# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
99# inherited members of a class in the documentation of that class as if those
100# members were ordinary class members. Constructors, destructors and assignment
101# operators of the base classes will not be shown.
102
103INLINE_INHERITED_MEMB = NO
104
105# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
106# path before files name in the file list and in the header files. If set
107# to NO the shortest path that makes the file name unique will be used.
108
109FULL_PATH_NAMES = NO
110
111# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
112# can be used to strip a user-defined part of the path. Stripping is
113# only done if one of the specified strings matches the left-hand part of
114# the path. The tag can be used to show relative paths in the file list.
115# If left blank the directory from which doxygen is run is used as the
116# path to strip.
117
118STRIP_FROM_PATH =
119
120# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
121# the path mentioned in the documentation of a class, which tells
122# the reader which header file to include in order to use a class.
123# If left blank only the name of the header file containing the class
124# definition is used. Otherwise one should specify the include paths that
125# are normally passed to the compiler using the -I flag.
126
127STRIP_FROM_INC_PATH =
128
129# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
130# (but less readable) file names. This can be useful is your file systems
131# doesn't support long names like on DOS, Mac, or CD-ROM.
132
133SHORT_NAMES = NO
134
135# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
136# will interpret the first line (until the first dot) of a JavaDoc-style
137# comment as the brief description. If set to NO, the JavaDoc
138# comments will behave just like the Qt-style comments (thus requiring an
139# explicit @brief command for a brief description.
140
141JAVADOC_AUTOBRIEF = NO
142
143# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
144# treat a multi-line C++ special comment block (i.e. a block of //! or ///
145# comments) as a brief description. This used to be the default behaviour.
146# The new default is to treat a multi-line C++ comment block as a detailed
147# description. Set this tag to YES if you prefer the old behaviour instead.
148
149MULTILINE_CPP_IS_BRIEF = NO
150
151# If the DETAILS_AT_TOP tag is set to YES then Doxygen
152# will output the detailed description near the top, like JavaDoc.
153# If set to NO, the detailed description appears after the member
154# documentation.
155
156DETAILS_AT_TOP = NO
157
158# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
159# member inherits the documentation from any documented member that it
160# re-implements.
161
162INHERIT_DOCS = YES
163
164# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
165# a new page for each member. If set to NO, the documentation of a member will
166# be part of the file/class/namespace that contains it.
167
168SEPARATE_MEMBER_PAGES = NO
169
170# The TAB_SIZE tag can be used to set the number of spaces in a tab.
171# Doxygen uses this value to replace tabs by spaces in code fragments.
172
173TAB_SIZE = 3
174
175# This tag can be used to specify a number of aliases that acts
176# as commands in the documentation. An alias has the form "name=value".
177# For example adding "sideeffect=\par Side Effects:\n" will allow you to
178# put the command \sideeffect (or @sideeffect) in the documentation, which
179# will result in a user-defined paragraph with heading "Side Effects:".
180# You can put \n's in the value part of an alias to insert newlines.
181
182ALIASES =
183
184# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
185# sources only. Doxygen will then generate output that is more tailored for C.
186# For instance, some of the names that are used will be different. The list
187# of all members will be omitted, etc.
188
189OPTIMIZE_OUTPUT_FOR_C = YES
190
191# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
192# sources only. Doxygen will then generate output that is more tailored for Java.
193# For instance, namespaces will be presented as packages, qualified scopes
194# will look different, etc.
195
196OPTIMIZE_OUTPUT_JAVA = NO
197
198# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
199# include (a tag file for) the STL sources as input, then you should
200# set this tag to YES in order to let doxygen match functions declarations and
201# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
202# func(std::string) {}). This also make the inheritance and collaboration
203# diagrams that involve STL classes more complete and accurate.
204
205BUILTIN_STL_SUPPORT = NO
206
207# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
208# tag is set to YES, then doxygen will reuse the documentation of the first
209# member in the group (if any) for the other members of the group. By default
210# all members of a group must be documented explicitly.
211
212DISTRIBUTE_GROUP_DOC = NO
213
214# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
215# the same type (for instance a group of public functions) to be put as a
216# subgroup of that type (e.g. under the Public Functions section). Set it to
217# NO to prevent subgrouping. Alternatively, this can be done per class using
218# the \nosubgrouping command.
219
220SUBGROUPING = YES
221
222#---------------------------------------------------------------------------
223# Build related configuration options
224#---------------------------------------------------------------------------
225
226# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
227# documentation are documented, even if no documentation was available.
228# Private class members and static file members will be hidden unless
229# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
230
231EXTRACT_ALL = NO
232
233# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
234# will be included in the documentation.
235
236EXTRACT_PRIVATE = NO
237
238# If the EXTRACT_STATIC tag is set to YES all static members of a file
239# will be included in the documentation.
240
241EXTRACT_STATIC = NO
242
243# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
244# defined locally in source files will be included in the documentation.
245# If set to NO only classes defined in header files are included.
246
247EXTRACT_LOCAL_CLASSES = YES
248
249# This flag is only useful for Objective-C code. When set to YES local
250# methods, which are defined in the implementation section but not in
251# the interface are included in the documentation.
252# If set to NO (the default) only methods in the interface are included.
253
254EXTRACT_LOCAL_METHODS = NO
255
256# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
257# undocumented members of documented classes, files or namespaces.
258# If set to NO (the default) these members will be included in the
259# various overviews, but no documentation section is generated.
260# This option has no effect if EXTRACT_ALL is enabled.
261
262HIDE_UNDOC_MEMBERS = NO
263
264# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
265# undocumented classes that are normally visible in the class hierarchy.
266# If set to NO (the default) these classes will be included in the various
267# overviews. This option has no effect if EXTRACT_ALL is enabled.
268
269HIDE_UNDOC_CLASSES = NO
270
271# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
272# friend (class|struct|union) declarations.
273# If set to NO (the default) these declarations will be included in the
274# documentation.
275
276HIDE_FRIEND_COMPOUNDS = NO
277
278# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
279# documentation blocks found inside the body of a function.
280# If set to NO (the default) these blocks will be appended to the
281# function's detailed documentation block.
282
283HIDE_IN_BODY_DOCS = NO
284
285# The INTERNAL_DOCS tag determines if documentation
286# that is typed after a \internal command is included. If the tag is set
287# to NO (the default) then the documentation will be excluded.
288# Set it to YES to include the internal documentation.
289
290INTERNAL_DOCS = NO
291
292# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
293# file names in lower-case letters. If set to YES upper-case letters are also
294# allowed. This is useful if you have classes or files whose names only differ
295# in case and if your file system supports case sensitive file names. Windows
296# and Mac users are advised to set this option to NO.
297
298CASE_SENSE_NAMES = NO
299
300# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
301# will show members with their full class and namespace scopes in the
302# documentation. If set to YES the scope will be hidden.
303
304HIDE_SCOPE_NAMES = NO
305
306# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
307# will put a list of the files that are included by a file in the documentation
308# of that file.
309
310SHOW_INCLUDE_FILES = YES
311
312# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
313# is inserted in the documentation for inline members.
314
315INLINE_INFO = YES
316
317# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
318# will sort the (detailed) documentation of file and class members
319# alphabetically by member name. If set to NO the members will appear in
320# declaration order.
321
322SORT_MEMBER_DOCS = YES
323
324# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
325# brief documentation of file, namespace and class members alphabetically
326# by member name. If set to NO (the default) the members will appear in
327# declaration order.
328
329SORT_BRIEF_DOCS = NO
330
331# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
332# sorted by fully-qualified names, including namespaces. If set to
333# NO (the default), the class list will be sorted only by class name,
334# not including the namespace part.
335# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
336# Note: This option applies only to the class list, not to the
337# alphabetical list.
338
339SORT_BY_SCOPE_NAME = NO
340
341# The GENERATE_TODOLIST tag can be used to enable (YES) or
342# disable (NO) the todo list. This list is created by putting \todo
343# commands in the documentation.
344
345GENERATE_TODOLIST = YES
346
347# The GENERATE_TESTLIST tag can be used to enable (YES) or
348# disable (NO) the test list. This list is created by putting \test
349# commands in the documentation.
350
351GENERATE_TESTLIST = YES
352
353# The GENERATE_BUGLIST tag can be used to enable (YES) or
354# disable (NO) the bug list. This list is created by putting \bug
355# commands in the documentation.
356
357GENERATE_BUGLIST = YES
358
359# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
360# disable (NO) the deprecated list. This list is created by putting
361# \deprecated commands in the documentation.
362
363GENERATE_DEPRECATEDLIST= YES
364
365# The ENABLED_SECTIONS tag can be used to enable conditional
366# documentation sections, marked by \if sectionname ... \endif.
367
368ENABLED_SECTIONS =
369
370# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
371# the initial value of a variable or define consists of for it to appear in
372# the documentation. If the initializer consists of more lines than specified
373# here it will be hidden. Use a value of 0 to hide initializers completely.
374# The appearance of the initializer of individual variables and defines in the
375# documentation can be controlled using \showinitializer or \hideinitializer
376# command in the documentation regardless of this setting.
377
378MAX_INITIALIZER_LINES = 30
379
380# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
381# at the bottom of the documentation of classes and structs. If set to YES the
382# list will mention the files that were used to generate the documentation.
383
384SHOW_USED_FILES = YES
385
386# If the sources in your project are distributed over multiple directories
387# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
388# in the documentation. The default is NO.
389
390SHOW_DIRECTORIES = NO
391
392# The FILE_VERSION_FILTER tag can be used to specify a program or script that
393# doxygen should invoke to get the current version for each file (typically from the
394# version control system). Doxygen will invoke the program by executing (via
395# popen()) the command <command> <input-file>, where <command> is the value of
396# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
397# provided by doxygen. Whatever the program writes to standard output
398# is used as the file version. See the manual for examples.
399
400FILE_VERSION_FILTER =
401
402#---------------------------------------------------------------------------
403# configuration options related to warning and progress messages
404#---------------------------------------------------------------------------
405
406# The QUIET tag can be used to turn on/off the messages that are generated
407# by doxygen. Possible values are YES and NO. If left blank NO is used.
408
409QUIET = NO
410
411# The WARNINGS tag can be used to turn on/off the warning messages that are
412# generated by doxygen. Possible values are YES and NO. If left blank
413# NO is used.
414
415WARNINGS = YES
416
417# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
418# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
419# automatically be disabled.
420
421WARN_IF_UNDOCUMENTED = YES
422
423# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
424# potential errors in the documentation, such as not documenting some
425# parameters in a documented function, or documenting parameters that
426# don't exist or using markup commands wrongly.
427
428WARN_IF_DOC_ERROR = YES
429
430# This WARN_NO_PARAMDOC option can be abled to get warnings for
431# functions that are documented, but have no documentation for their parameters
432# or return value. If set to NO (the default) doxygen will only warn about
433# wrong or incomplete parameter documentation, but not about the absence of
434# documentation.
435
436WARN_NO_PARAMDOC = NO
437
438# The WARN_FORMAT tag determines the format of the warning messages that
439# doxygen can produce. The string should contain the $file, $line, and $text
440# tags, which will be replaced by the file and line number from which the
441# warning originated and the warning text. Optionally the format may contain
442# $version, which will be replaced by the version of the file (if it could
443# be obtained via FILE_VERSION_FILTER)
444
445WARN_FORMAT = "$file:$line: $text"
446
447# The WARN_LOGFILE tag can be used to specify a file to which warning
448# and error messages should be written. If left blank the output is written
449# to stderr.
450
451WARN_LOGFILE =
452
453#---------------------------------------------------------------------------
454# configuration options related to the input files
455#---------------------------------------------------------------------------
456
457# The INPUT tag can be used to specify the files and/or directories that contain
458# documented source files. You may enter file names like "myfile.cpp" or
459# directories like "/usr/src/myproject". Separate the files or directories
460# with spaces.
461
462INPUT = . ../../include/ode ../../include/drawstuff
463
464# If the value of the INPUT tag contains directories, you can use the
465# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
466# and *.h) to filter out the source-files in the directories. If left
467# blank the following patterns are tested:
468# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
469# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
470
471FILE_PATTERNS = *.h *.c *.cpp *.dox
472
473# The RECURSIVE tag can be used to turn specify whether or not subdirectories
474# should be searched for input files as well. Possible values are YES and NO.
475# If left blank NO is used.
476
477RECURSIVE = NO
478
479# The EXCLUDE tag can be used to specify files and/or directories that should
480# excluded from the INPUT source files. This way you can easily exclude a
481# subdirectory from a directory tree whose root is specified with the INPUT tag.
482
483EXCLUDE =
484
485# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
486# directories that are symbolic links (a Unix filesystem feature) are excluded
487# from the input.
488
489EXCLUDE_SYMLINKS = NO
490
491# If the value of the INPUT tag contains directories, you can use the
492# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
493# certain files from those directories. Note that the wildcards are matched
494# against the file with absolute path, so to exclude all test directories
495# for example use the pattern */test/*
496
497EXCLUDE_PATTERNS =
498
499# The EXAMPLE_PATH tag can be used to specify one or more files or
500# directories that contain example code fragments that are included (see
501# the \include command).
502
503EXAMPLE_PATH =
504
505# If the value of the EXAMPLE_PATH tag contains directories, you can use the
506# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
507# and *.h) to filter out the source-files in the directories. If left
508# blank all files are included.
509
510EXAMPLE_PATTERNS =
511
512# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
513# searched for input files to be used with the \include or \dontinclude
514# commands irrespective of the value of the RECURSIVE tag.
515# Possible values are YES and NO. If left blank NO is used.
516
517EXAMPLE_RECURSIVE = NO
518
519# The IMAGE_PATH tag can be used to specify one or more files or
520# directories that contain image that are included in the documentation (see
521# the \image command).
522
523IMAGE_PATH = pix
524
525# The INPUT_FILTER tag can be used to specify a program that doxygen should
526# invoke to filter for each input file. Doxygen will invoke the filter program
527# by executing (via popen()) the command <filter> <input-file>, where <filter>
528# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
529# input file. Doxygen will then use the output that the filter program writes
530# to standard output. If FILTER_PATTERNS is specified, this tag will be
531# ignored.
532
533INPUT_FILTER =
534
535# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
536# basis. Doxygen will compare the file name with each pattern and apply the
537# filter if there is a match. The filters are a list of the form:
538# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
539# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
540# is applied to all files.
541
542FILTER_PATTERNS =
543
544# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
545# INPUT_FILTER) will be used to filter the input files when producing source
546# files to browse (i.e. when SOURCE_BROWSER is set to YES).
547
548FILTER_SOURCE_FILES = NO
549
550#---------------------------------------------------------------------------
551# configuration options related to source browsing
552#---------------------------------------------------------------------------
553
554# If the SOURCE_BROWSER tag is set to YES then a list of source files will
555# be generated. Documented entities will be cross-referenced with these sources.
556# Note: To get rid of all source code in the generated output, make sure also
557# VERBATIM_HEADERS is set to NO.
558
559SOURCE_BROWSER = NO
560
561# Setting the INLINE_SOURCES tag to YES will include the body
562# of functions and classes directly in the documentation.
563
564INLINE_SOURCES = NO
565
566# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
567# doxygen to hide any special comment blocks from generated source code
568# fragments. Normal C and C++ comments will always remain visible.
569
570STRIP_CODE_COMMENTS = YES
571
572# If the REFERENCED_BY_RELATION tag is set to YES (the default)
573# then for each documented function all documented
574# functions referencing it will be listed.
575
576REFERENCED_BY_RELATION = YES
577
578# If the REFERENCES_RELATION tag is set to YES (the default)
579# then for each documented function all documented entities
580# called/used by that function will be listed.
581
582REFERENCES_RELATION = YES
583
584# If the USE_HTAGS tag is set to YES then the references to source code
585# will point to the HTML generated by the htags(1) tool instead of doxygen
586# built-in source browser. The htags tool is part of GNU's global source
587# tagging system (see http://www.gnu.org/software/global/global.html). You
588# will need version 4.8.6 or higher.
589
590USE_HTAGS = NO
591
592# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
593# will generate a verbatim copy of the header file for each class for
594# which an include is specified. Set to NO to disable this.
595
596VERBATIM_HEADERS = YES
597
598#---------------------------------------------------------------------------
599# configuration options related to the alphabetical class index
600#---------------------------------------------------------------------------
601
602# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
603# of all compounds will be generated. Enable this if the project
604# contains a lot of classes, structs, unions or interfaces.
605
606ALPHABETICAL_INDEX = NO
607
608# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
609# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
610# in which this list will be split (can be a number in the range [1..20])
611
612COLS_IN_ALPHA_INDEX = 5
613
614# In case all classes in a project start with a common prefix, all
615# classes will be put under the same header in the alphabetical index.
616# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
617# should be ignored while generating the index headers.
618
619IGNORE_PREFIX =
620
621#---------------------------------------------------------------------------
622# configuration options related to the HTML output
623#---------------------------------------------------------------------------
624
625# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
626# generate HTML output.
627
628GENERATE_HTML = YES
629
630# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
631# If a relative path is entered the value of OUTPUT_DIRECTORY will be
632# put in front of it. If left blank `html' will be used as the default path.
633
634HTML_OUTPUT = .
635
636# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
637# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
638# doxygen will generate files with .html extension.
639
640HTML_FILE_EXTENSION = .html
641
642# The HTML_HEADER tag can be used to specify a personal HTML header for
643# each generated HTML page. If it is left blank doxygen will generate a
644# standard header.
645
646HTML_HEADER =
647
648# The HTML_FOOTER tag can be used to specify a personal HTML footer for
649# each generated HTML page. If it is left blank doxygen will generate a
650# standard footer.
651
652HTML_FOOTER =
653
654# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
655# style sheet that is used by each HTML page. It can be used to
656# fine-tune the look of the HTML output. If the tag is left blank doxygen
657# will generate a default style sheet. Note that doxygen will try to copy
658# the style sheet file to the HTML output directory, so don't put your own
659# stylesheet in the HTML output directory as well, or it will be erased!
660
661HTML_STYLESHEET =
662
663# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
664# files or namespaces will be aligned in HTML using tables. If set to
665# NO a bullet list will be used.
666
667HTML_ALIGN_MEMBERS = YES
668
669# If the GENERATE_HTMLHELP tag is set to YES, additional index files
670# will be generated that can be used as input for tools like the
671# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
672# of the generated HTML documentation.
673
674GENERATE_HTMLHELP = NO
675
676# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
677# be used to specify the file name of the resulting .chm file. You
678# can add a path in front of the file if the result should not be
679# written to the html output directory.
680
681CHM_FILE =
682
683# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
684# be used to specify the location (absolute path including file name) of
685# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
686# the HTML help compiler on the generated index.hhp.
687
688HHC_LOCATION =
689
690# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
691# controls if a separate .chi index file is generated (YES) or that
692# it should be included in the master .chm file (NO).
693
694GENERATE_CHI = NO
695
696# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
697# controls whether a binary table of contents is generated (YES) or a
698# normal table of contents (NO) in the .chm file.
699
700BINARY_TOC = NO
701
702# The TOC_EXPAND flag can be set to YES to add extra items for group members
703# to the contents of the HTML help documentation and to the tree view.
704
705TOC_EXPAND = NO
706
707# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
708# top of each HTML page. The value NO (the default) enables the index and
709# the value YES disables it.
710
711DISABLE_INDEX = NO
712
713# This tag can be used to set the number of enum values (range [1..20])
714# that doxygen will group on one line in the generated HTML documentation.
715
716ENUM_VALUES_PER_LINE = 4
717
718# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
719# generated containing a tree-like index structure (just like the one that
720# is generated for HTML Help). For this to work a browser that supports
721# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
722# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
723# probably better off using the HTML help feature.
724
725GENERATE_TREEVIEW = NO
726
727# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
728# used to set the initial width (in pixels) of the frame in which the tree
729# is shown.
730
731TREEVIEW_WIDTH = 250
732
733#---------------------------------------------------------------------------
734# configuration options related to the LaTeX output
735#---------------------------------------------------------------------------
736
737# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
738# generate Latex output.
739
740GENERATE_LATEX = NO
741
742# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
743# If a relative path is entered the value of OUTPUT_DIRECTORY will be
744# put in front of it. If left blank `latex' will be used as the default path.
745
746LATEX_OUTPUT = latex
747
748# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
749# invoked. If left blank `latex' will be used as the default command name.
750
751LATEX_CMD_NAME = latex
752
753# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
754# generate index for LaTeX. If left blank `makeindex' will be used as the
755# default command name.
756
757MAKEINDEX_CMD_NAME = makeindex
758
759# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
760# LaTeX documents. This may be useful for small projects and may help to
761# save some trees in general.
762
763COMPACT_LATEX = NO
764
765# The PAPER_TYPE tag can be used to set the paper type that is used
766# by the printer. Possible values are: a4, a4wide, letter, legal and
767# executive. If left blank a4wide will be used.
768
769PAPER_TYPE = a4wide
770
771# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
772# packages that should be included in the LaTeX output.
773
774EXTRA_PACKAGES =
775
776# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
777# the generated latex document. The header should contain everything until
778# the first chapter. If it is left blank doxygen will generate a
779# standard header. Notice: only use this tag if you know what you are doing!
780
781LATEX_HEADER =
782
783# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
784# is prepared for conversion to pdf (using ps2pdf). The pdf file will
785# contain links (just like the HTML output) instead of page references
786# This makes the output suitable for online browsing using a pdf viewer.
787
788PDF_HYPERLINKS = NO
789
790# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
791# plain latex in the generated Makefile. Set this option to YES to get a
792# higher quality PDF documentation.
793
794USE_PDFLATEX = NO
795
796# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
797# command to the generated LaTeX files. This will instruct LaTeX to keep
798# running if errors occur, instead of asking the user for help.
799# This option is also used when generating formulas in HTML.
800
801LATEX_BATCHMODE = NO
802
803# If LATEX_HIDE_INDICES is set to YES then doxygen will not
804# include the index chapters (such as File Index, Compound Index, etc.)
805# in the output.
806
807LATEX_HIDE_INDICES = NO
808
809#---------------------------------------------------------------------------
810# configuration options related to the RTF output
811#---------------------------------------------------------------------------
812
813# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
814# The RTF output is optimized for Word 97 and may not look very pretty with
815# other RTF readers or editors.
816
817GENERATE_RTF = NO
818
819# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
820# If a relative path is entered the value of OUTPUT_DIRECTORY will be
821# put in front of it. If left blank `rtf' will be used as the default path.
822
823RTF_OUTPUT = rtf
824
825# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
826# RTF documents. This may be useful for small projects and may help to
827# save some trees in general.
828
829COMPACT_RTF = NO
830
831# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
832# will contain hyperlink fields. The RTF file will
833# contain links (just like the HTML output) instead of page references.
834# This makes the output suitable for online browsing using WORD or other
835# programs which support those fields.
836# Note: wordpad (write) and others do not support links.
837
838RTF_HYPERLINKS = NO
839
840# Load stylesheet definitions from file. Syntax is similar to doxygen's
841# config file, i.e. a series of assignments. You only have to provide
842# replacements, missing definitions are set to their default value.
843
844RTF_STYLESHEET_FILE =
845
846# Set optional variables used in the generation of an rtf document.
847# Syntax is similar to doxygen's config file.
848
849RTF_EXTENSIONS_FILE =
850
851#---------------------------------------------------------------------------
852# configuration options related to the man page output
853#---------------------------------------------------------------------------
854
855# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
856# generate man pages
857
858GENERATE_MAN = NO
859
860# The MAN_OUTPUT tag is used to specify where the man pages will be put.
861# If a relative path is entered the value of OUTPUT_DIRECTORY will be
862# put in front of it. If left blank `man' will be used as the default path.
863
864MAN_OUTPUT = man
865
866# The MAN_EXTENSION tag determines the extension that is added to
867# the generated man pages (default is the subroutine's section .3)
868
869MAN_EXTENSION = .3
870
871# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
872# then it will generate one additional man file for each entity
873# documented in the real man page(s). These additional files
874# only source the real man page, but without them the man command
875# would be unable to find the correct page. The default is NO.
876
877MAN_LINKS = NO
878
879#---------------------------------------------------------------------------
880# configuration options related to the XML output
881#---------------------------------------------------------------------------
882
883# If the GENERATE_XML tag is set to YES Doxygen will
884# generate an XML file that captures the structure of
885# the code including all documentation.
886
887GENERATE_XML = NO
888
889# The XML_OUTPUT tag is used to specify where the XML pages will be put.
890# If a relative path is entered the value of OUTPUT_DIRECTORY will be
891# put in front of it. If left blank `xml' will be used as the default path.
892
893XML_OUTPUT = xml
894
895# The XML_SCHEMA tag can be used to specify an XML schema,
896# which can be used by a validating XML parser to check the
897# syntax of the XML files.
898
899XML_SCHEMA =
900
901# The XML_DTD tag can be used to specify an XML DTD,
902# which can be used by a validating XML parser to check the
903# syntax of the XML files.
904
905XML_DTD =
906
907# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
908# dump the program listings (including syntax highlighting
909# and cross-referencing information) to the XML output. Note that
910# enabling this will significantly increase the size of the XML output.
911
912XML_PROGRAMLISTING = YES
913
914#---------------------------------------------------------------------------
915# configuration options for the AutoGen Definitions output
916#---------------------------------------------------------------------------
917
918# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
919# generate an AutoGen Definitions (see autogen.sf.net) file
920# that captures the structure of the code including all
921# documentation. Note that this feature is still experimental
922# and incomplete at the moment.
923
924GENERATE_AUTOGEN_DEF = NO
925
926#---------------------------------------------------------------------------
927# configuration options related to the Perl module output
928#---------------------------------------------------------------------------
929
930# If the GENERATE_PERLMOD tag is set to YES Doxygen will
931# generate a Perl module file that captures the structure of
932# the code including all documentation. Note that this
933# feature is still experimental and incomplete at the
934# moment.
935
936GENERATE_PERLMOD = NO
937
938# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
939# the necessary Makefile rules, Perl scripts and LaTeX code to be able
940# to generate PDF and DVI output from the Perl module output.
941
942PERLMOD_LATEX = NO
943
944# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
945# nicely formatted so it can be parsed by a human reader. This is useful
946# if you want to understand what is going on. On the other hand, if this
947# tag is set to NO the size of the Perl module output will be much smaller
948# and Perl will parse it just the same.
949
950PERLMOD_PRETTY = YES
951
952# The names of the make variables in the generated doxyrules.make file
953# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
954# This is useful so different doxyrules.make files included by the same
955# Makefile don't overwrite each other's variables.
956
957PERLMOD_MAKEVAR_PREFIX =
958
959#---------------------------------------------------------------------------
960# Configuration options related to the preprocessor
961#---------------------------------------------------------------------------
962
963# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
964# evaluate all C-preprocessor directives found in the sources and include
965# files.
966
967ENABLE_PREPROCESSING = YES
968
969# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
970# names in the source code. If set to NO (the default) only conditional
971# compilation will be performed. Macro expansion can be done in a controlled
972# way by setting EXPAND_ONLY_PREDEF to YES.
973
974MACRO_EXPANSION = NO
975
976# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
977# then the macro expansion is limited to the macros specified with the
978# PREDEFINED and EXPAND_AS_DEFINED tags.
979
980EXPAND_ONLY_PREDEF = NO
981
982# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
983# in the INCLUDE_PATH (see below) will be search if a #include is found.
984
985SEARCH_INCLUDES = YES
986
987# The INCLUDE_PATH tag can be used to specify one or more directories that
988# contain include files that are not input files but should be processed by
989# the preprocessor.
990
991INCLUDE_PATH =
992
993# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
994# patterns (like *.h and *.hpp) to filter out the header-files in the
995# directories. If left blank, the patterns specified with FILE_PATTERNS will
996# be used.
997
998INCLUDE_FILE_PATTERNS =
999
1000# The PREDEFINED tag can be used to specify one or more macro names that
1001# are defined before the preprocessor is started (similar to the -D option of
1002# gcc). The argument of the tag is a list of macros of the form: name
1003# or name=definition (no spaces). If the definition and the = are
1004# omitted =1 is assumed. To prevent a macro definition from being
1005# undefined via #undef or recursively expanded use the := operator
1006# instead of the = operator.
1007
1008PREDEFINED =
1009
1010# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
1011# this tag can be used to specify a list of macro names that should be expanded.
1012# The macro definition that is found in the sources will be used.
1013# Use the PREDEFINED tag if you want to use a different macro definition.
1014
1015EXPAND_AS_DEFINED =
1016
1017# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
1018# doxygen's preprocessor will remove all function-like macros that are alone
1019# on a line, have an all uppercase name, and do not end with a semicolon. Such
1020# function macros are typically used for boiler-plate code, and will confuse
1021# the parser if not removed.
1022
1023SKIP_FUNCTION_MACROS = YES
1024
1025#---------------------------------------------------------------------------
1026# Configuration::additions related to external references
1027#---------------------------------------------------------------------------
1028
1029# The TAGFILES option can be used to specify one or more tagfiles.
1030# Optionally an initial location of the external documentation
1031# can be added for each tagfile. The format of a tag file without
1032# this location is as follows:
1033# TAGFILES = file1 file2 ...
1034# Adding location for the tag files is done as follows:
1035# TAGFILES = file1=loc1 "file2 = loc2" ...
1036# where "loc1" and "loc2" can be relative or absolute paths or
1037# URLs. If a location is present for each tag, the installdox tool
1038# does not have to be run to correct the links.
1039# Note that each tag file must have a unique name
1040# (where the name does NOT include the path)
1041# If a tag file is not located in the directory in which doxygen
1042# is run, you must also specify the path to the tagfile here.
1043
1044TAGFILES =
1045
1046# When a file name is specified after GENERATE_TAGFILE, doxygen will create
1047# a tag file that is based on the input files it reads.
1048
1049GENERATE_TAGFILE =
1050
1051# If the ALLEXTERNALS tag is set to YES all external classes will be listed
1052# in the class index. If set to NO only the inherited external classes
1053# will be listed.
1054
1055ALLEXTERNALS = NO
1056
1057# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
1058# in the modules index. If set to NO, only the current project's groups will
1059# be listed.
1060
1061EXTERNAL_GROUPS = YES
1062
1063# The PERL_PATH should be the absolute path and name of the perl script
1064# interpreter (i.e. the result of `which perl').
1065
1066PERL_PATH = /usr/bin/perl
1067
1068#---------------------------------------------------------------------------
1069# Configuration options related to the dot tool
1070#---------------------------------------------------------------------------
1071
1072# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
1073# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
1074# or super classes. Setting the tag to NO turns the diagrams off. Note that
1075# this option is superseded by the HAVE_DOT option below. This is only a
1076# fallback. It is recommended to install and use dot, since it yields more
1077# powerful graphs.
1078
1079CLASS_DIAGRAMS = YES
1080
1081# If set to YES, the inheritance and collaboration graphs will hide
1082# inheritance and usage relations if the target is undocumented
1083# or is not a class.
1084
1085HIDE_UNDOC_RELATIONS = YES
1086
1087# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
1088# available from the path. This tool is part of Graphviz, a graph visualization
1089# toolkit from AT&T and Lucent Bell Labs. The other options in this section
1090# have no effect if this option is set to NO (the default)
1091
1092HAVE_DOT = NO
1093
1094# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
1095# will generate a graph for each documented class showing the direct and
1096# indirect inheritance relations. Setting this tag to YES will force the
1097# the CLASS_DIAGRAMS tag to NO.
1098
1099CLASS_GRAPH = YES
1100
1101# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
1102# will generate a graph for each documented class showing the direct and
1103# indirect implementation dependencies (inheritance, containment, and
1104# class references variables) of the class with other documented classes.
1105
1106COLLABORATION_GRAPH = YES
1107
1108# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
1109# will generate a graph for groups, showing the direct groups dependencies
1110
1111GROUP_GRAPHS = YES
1112
1113# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
1114# collaboration diagrams in a style similar to the OMG's Unified Modeling
1115# Language.
1116
1117UML_LOOK = NO
1118
1119# If set to YES, the inheritance and collaboration graphs will show the
1120# relations between templates and their instances.
1121
1122TEMPLATE_RELATIONS = NO
1123
1124# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
1125# tags are set to YES then doxygen will generate a graph for each documented
1126# file showing the direct and indirect include dependencies of the file with
1127# other documented files.
1128
1129INCLUDE_GRAPH = YES
1130
1131# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
1132# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
1133# documented header file showing the documented files that directly or
1134# indirectly include this file.
1135
1136INCLUDED_BY_GRAPH = YES
1137
1138# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
1139# generate a call dependency graph for every global function or class method.
1140# Note that enabling this option will significantly increase the time of a run.
1141# So in most cases it will be better to enable call graphs for selected
1142# functions only using the \callgraph command.
1143
1144CALL_GRAPH = NO
1145
1146# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
1147# will graphical hierarchy of all classes instead of a textual one.
1148
1149GRAPHICAL_HIERARCHY = YES
1150
1151# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
1152# then doxygen will show the dependencies a directory has on other directories
1153# in a graphical way. The dependency relations are determined by the #include
1154# relations between the files in the directories.
1155
1156DIRECTORY_GRAPH = YES
1157
1158# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
1159# generated by dot. Possible values are png, jpg, or gif
1160# If left blank png will be used.
1161
1162DOT_IMAGE_FORMAT = png
1163
1164# The tag DOT_PATH can be used to specify the path where the dot tool can be
1165# found. If left blank, it is assumed the dot tool can be found in the path.
1166
1167DOT_PATH =
1168
1169# The DOTFILE_DIRS tag can be used to specify one or more directories that
1170# contain dot files that are included in the documentation (see the
1171# \dotfile command).
1172
1173DOTFILE_DIRS =
1174
1175# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
1176# (in pixels) of the graphs generated by dot. If a graph becomes larger than
1177# this value, doxygen will try to truncate the graph, so that it fits within
1178# the specified constraint. Beware that most browsers cannot cope with very
1179# large images.
1180
1181MAX_DOT_GRAPH_WIDTH = 1024
1182
1183# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
1184# (in pixels) of the graphs generated by dot. If a graph becomes larger than
1185# this value, doxygen will try to truncate the graph, so that it fits within
1186# the specified constraint. Beware that most browsers cannot cope with very
1187# large images.
1188
1189MAX_DOT_GRAPH_HEIGHT = 1024
1190
1191# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
1192# graphs generated by dot. A depth value of 3 means that only nodes reachable
1193# from the root by following a path via at most 3 edges will be shown. Nodes
1194# that lay further from the root node will be omitted. Note that setting this
1195# option to 1 or 2 may greatly reduce the computation time needed for large
1196# code bases. Also note that a graph may be further truncated if the graph's
1197# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
1198# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
1199# the graph is not depth-constrained.
1200
1201MAX_DOT_GRAPH_DEPTH = 0
1202
1203# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
1204# background. This is disabled by default, which results in a white background.
1205# Warning: Depending on the platform used, enabling this option may lead to
1206# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
1207# read).
1208
1209DOT_TRANSPARENT = NO
1210
1211# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
1212# files in one run (i.e. multiple -o and -T options on the command line). This
1213# makes dot run faster, but since only newer versions of dot (>1.8.10)
1214# support this, this feature is disabled by default.
1215
1216DOT_MULTI_TARGETS = NO
1217
1218# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
1219# generate a legend page explaining the meaning of the various boxes and
1220# arrows in the dot generated graphs.
1221
1222GENERATE_LEGEND = YES
1223
1224# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
1225# remove the intermediate dot files that are used to generate
1226# the various graphs.
1227
1228DOT_CLEANUP = YES
1229
1230#---------------------------------------------------------------------------
1231# Configuration::additions related to the search engine
1232#---------------------------------------------------------------------------
1233
1234# The SEARCHENGINE tag specifies whether or not a search engine should be
1235# used. If set to NO the values of all tags below this one will be ignored.
1236
1237SEARCHENGINE = NO
diff --git a/libraries/ode-0.9/ode/doc/main.dox b/libraries/ode-0.9/ode/doc/main.dox
deleted file mode 100644
index 5136c33..0000000
--- a/libraries/ode-0.9/ode/doc/main.dox
+++ /dev/null
@@ -1,22 +0,0 @@
1/**
2@mainpage Open Dynamics Engine API Reference
3
4<center><em>This document is &copy; Russell Smith and the ODE Project</em></center>
5
6The Open Dynamics Engine (ODE) is a free, industrial quality library for
7simulating articulated rigid body dynamics. ODE is being developed by
8<a href="http://www.q12.org/">Russell Smith</a> with help from several
9<a href="http://ode.org/community.html">contributors</a>.
10
11This document describes the library API. For a more general introduction
12to ODE, please see the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">
13Online Handbook</a>.
14
15<h2>Important: this document is not yet complete!</h2>
16
17We are still working on getting the full API documentated. In the meantime,
18please refer to the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">
19Online Handbook</a>
20
21*/
22
diff --git a/libraries/ode-0.9/ode/doc/pix/amotor.jpg b/libraries/ode-0.9/ode/doc/pix/amotor.jpg
deleted file mode 100644
index bb80810..0000000
--- a/libraries/ode-0.9/ode/doc/pix/amotor.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/ball-and-socket-bad.jpg b/libraries/ode-0.9/ode/doc/pix/ball-and-socket-bad.jpg
deleted file mode 100644
index 90abaf3..0000000
--- a/libraries/ode-0.9/ode/doc/pix/ball-and-socket-bad.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/ball-and-socket.jpg b/libraries/ode-0.9/ode/doc/pix/ball-and-socket.jpg
deleted file mode 100644
index 050e136..0000000
--- a/libraries/ode-0.9/ode/doc/pix/ball-and-socket.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/body.jpg b/libraries/ode-0.9/ode/doc/pix/body.jpg
deleted file mode 100644
index e026b93..0000000
--- a/libraries/ode-0.9/ode/doc/pix/body.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/contact.jpg b/libraries/ode-0.9/ode/doc/pix/contact.jpg
deleted file mode 100644
index 5d96809..0000000
--- a/libraries/ode-0.9/ode/doc/pix/contact.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/hinge.jpg b/libraries/ode-0.9/ode/doc/pix/hinge.jpg
deleted file mode 100644
index ffd634e..0000000
--- a/libraries/ode-0.9/ode/doc/pix/hinge.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/hinge2.jpg b/libraries/ode-0.9/ode/doc/pix/hinge2.jpg
deleted file mode 100644
index fda5e94..0000000
--- a/libraries/ode-0.9/ode/doc/pix/hinge2.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/joints.jpg b/libraries/ode-0.9/ode/doc/pix/joints.jpg
deleted file mode 100644
index 188ed01..0000000
--- a/libraries/ode-0.9/ode/doc/pix/joints.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/rollingcontact.jpg b/libraries/ode-0.9/ode/doc/pix/rollingcontact.jpg
deleted file mode 100644
index b20bd1b..0000000
--- a/libraries/ode-0.9/ode/doc/pix/rollingcontact.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/sf-graph1.jpg b/libraries/ode-0.9/ode/doc/pix/sf-graph1.jpg
deleted file mode 100644
index aee4ca7..0000000
--- a/libraries/ode-0.9/ode/doc/pix/sf-graph1.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/sf-graph2.jpg b/libraries/ode-0.9/ode/doc/pix/sf-graph2.jpg
deleted file mode 100644
index 67d08bc..0000000
--- a/libraries/ode-0.9/ode/doc/pix/sf-graph2.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/slider.jpg b/libraries/ode-0.9/ode/doc/pix/slider.jpg
deleted file mode 100644
index 040f76f..0000000
--- a/libraries/ode-0.9/ode/doc/pix/slider.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/doc/pix/universal.jpg b/libraries/ode-0.9/ode/doc/pix/universal.jpg
deleted file mode 100644
index bc63523..0000000
--- a/libraries/ode-0.9/ode/doc/pix/universal.jpg
+++ /dev/null
Binary files differ
diff --git a/libraries/ode-0.9/ode/src/Makefile.am b/libraries/ode-0.9/ode/src/Makefile.am
deleted file mode 100644
index 1b0cf19..0000000
--- a/libraries/ode-0.9/ode/src/Makefile.am
+++ /dev/null
@@ -1,207 +0,0 @@
1AM_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
2AM_CPPFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
3AM_CFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
4lib_LIBRARIES = libode.a
5libode_a_CPPFLAGS = -O2
6
7libode_a_CPPFLAGS += -fPIC
8
9# Fake an executable in order to get a shared library
10# Note the elegant and cunning way to trick Autotools to install a program
11# in a lib directory. --Rodrigo
12traplibdir=$(libdir)
13EXEEXT=@so_ext@
14traplib_PROGRAMS=libode
15libode_SOURCES=
16libode_DEPENDENCIES = libfast.a libode.a
17libode_LDFLAGS= @SHARED_LDFLAGS@
18if USE_SONAME
19libode_LDFLAGS+=-Wl,-soname,@ODE_SONAME@
20endif
21libode_LDADD=$(libode_a_OBJECTS) $(libfast_a_OBJECTS)
22
23if OPCODE
24libode_DEPENDENCIES+= libOPCODE.a
25libode_LDADD+=$(libOPCODE_a_OBJECTS)
26endif
27
28
29if GIMPACT
30libode_DEPENDENCIES+= libGIMPACT.a
31libode_LDADD+=$(libGIMPACT_a_OBJECTS)
32endif
33
34
35# convenience library to simulate per object cflags
36noinst_LIBRARIES= libfast.a
37libfast_a_CFLAGS= -O1
38libfast_a_SOURCES= fastldlt.c fastltsolve.c fastdot.c fastlsolve.c
39
40libfast_a_CFLAGS += -fPIC
41
42libode_a_DEPENDENCIES = libfast.a
43libode_a_LIBADD= $(libfast_a_OBJECTS)
44
45libode_a_SOURCES = objects.h \
46 obstack.cpp \
47 collision_util.cpp \
48 obstack.h \
49 array.cpp \
50 collision_util.h \
51 ode.cpp \
52 array.h \
53 error.cpp \
54 odemath.cpp \
55 collision_kernel.cpp \
56 export-dif.cpp \
57 quickstep.cpp \
58 collision_kernel.h \
59 quickstep.h \
60 collision_quadtreespace.cpp \
61 rotation.cpp \
62 collision_space.cpp \
63 collision_space_internal.h \
64 collision_cylinder_box.cpp \
65 collision_cylinder_sphere.cpp \
66 collision_cylinder_plane.cpp \
67 sphere.cpp \
68 box.cpp \
69 capsule.cpp \
70 plane.cpp \
71 ray.cpp \
72 cylinder.cpp \
73 convex.cpp \
74 joint.cpp \
75 stack.h \
76 collision_std.h \
77 joint.h \
78 step.cpp \
79 collision_transform.cpp \
80 lcp.cpp \
81 step.h \
82 collision_transform.h \
83 lcp.h \
84 stepfast.cpp \
85 mass.cpp \
86 testing.cpp \
87 mat.cpp \
88 testing.h \
89 mat.h \
90 timer.cpp \
91 matrix.cpp \
92 util.cpp \
93 memory.cpp \
94 util.h \
95 misc.cpp \
96 heightfield.cpp \
97 heightfield.h
98
99
100
101###################################
102# G I M P A C T S T U F F
103###################################
104
105
106if GIMPACT
107noinst_LIBRARIES+= libGIMPACT.a
108libGIMPACT_a_CPPFLAGS= -O2 -fno-strict-aliasing -fPIC
109
110libode_a_SOURCES+= collision_trimesh_gimpact.cpp
111
112libGIMPACT_a_SOURCES = \
113 @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
114 @TOPDIR@/GIMPACT/src/gim_contact.cpp \
115 @TOPDIR@/GIMPACT/src/gim_math.cpp \
116 @TOPDIR@/GIMPACT/src/gim_memory.cpp \
117 @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
118 @TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
119 @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
120 @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
121 @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
122 @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
123 @TOPDIR@/GIMPACT/src/gimpact.cpp
124
125libode_a_DEPENDENCIES+=libGIMPACT.a
126libode_a_LIBADD+= $(libGIMPACT_a_OBJECTS)
127AM_CXXFLAGS += -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
128AM_CFLAGS += -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
129
130libode_a_SOURCES+= collision_trimesh_trimesh.cpp \
131 collision_trimesh_sphere.cpp \
132 collision_trimesh_ray.cpp \
133 collision_trimesh_opcode.cpp \
134 collision_trimesh_box.cpp \
135 collision_trimesh_ccylinder.cpp \
136 collision_trimesh_distance.cpp \
137 collision_trimesh_internal.h \
138 collision_cylinder_trimesh.cpp \
139 collision_trimesh_plane.cpp
140endif
141
142
143
144#################################
145# O P C O D E S T U F F
146#################################
147
148
149if OPCODE
150noinst_LIBRARIES+= libOPCODE.a
151libOPCODE_a_CPPFLAGS= -O2 -fno-strict-aliasing -fPIC
152
153
154libOPCODE_a_SOURCES= @TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
155 @TOPDIR@/OPCODE/OPC_AABBTree.cpp \
156 @TOPDIR@/OPCODE/OPC_BaseModel.cpp \
157 @TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
158 @TOPDIR@/OPCODE/OPC_Collider.cpp \
159 @TOPDIR@/OPCODE/OPC_Common.cpp \
160 @TOPDIR@/OPCODE/OPC_HybridModel.cpp \
161 @TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
162 @TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
163 @TOPDIR@/OPCODE/OPC_Model.cpp \
164 @TOPDIR@/OPCODE/OPC_OBBCollider.cpp \
165 @TOPDIR@/OPCODE/Opcode.cpp \
166 @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
167 @TOPDIR@/OPCODE/OPC_Picking.cpp \
168 @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
169 @TOPDIR@/OPCODE/OPC_RayCollider.cpp \
170 @TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
171 @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
172 @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
173 @TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
174 @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
175 @TOPDIR@/OPCODE/Ice/IceAABB.cpp \
176 @TOPDIR@/OPCODE/Ice/IceContainer.cpp \
177 @TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
178 @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
179 @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
180 @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
181 @TOPDIR@/OPCODE/Ice/IceOBB.cpp \
182 @TOPDIR@/OPCODE/Ice/IcePlane.cpp \
183 @TOPDIR@/OPCODE/Ice/IcePoint.cpp \
184 @TOPDIR@/OPCODE/Ice/IceRandom.cpp \
185 @TOPDIR@/OPCODE/Ice/IceRay.cpp \
186 @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
187 @TOPDIR@/OPCODE/Ice/IceSegment.cpp \
188 @TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
189 @TOPDIR@/OPCODE/Ice/IceUtils.cpp
190libode_a_DEPENDENCIES+=libOPCODE.a
191
192libode_a_LIBADD+= $(libOPCODE_a_OBJECTS)
193AM_CXXFLAGS += -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
194AM_CFLAGS += -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
195libode_a_SOURCES+= collision_trimesh_trimesh.cpp \
196 collision_trimesh_sphere.cpp \
197 collision_trimesh_ray.cpp \
198 collision_trimesh_opcode.cpp \
199 collision_trimesh_box.cpp \
200 collision_trimesh_ccylinder.cpp \
201 collision_trimesh_distance.cpp \
202 collision_trimesh_internal.h \
203 collision_cylinder_trimesh.cpp \
204 collision_trimesh_plane.cpp
205endif
206
207
diff --git a/libraries/ode-0.9/ode/src/Makefile.in b/libraries/ode-0.9/ode/src/Makefile.in
deleted file mode 100644
index 548f2e2..0000000
--- a/libraries/ode-0.9/ode/src/Makefile.in
+++ /dev/null
@@ -1,2290 +0,0 @@
1# Makefile.in generated by automake 1.10 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
6# This Makefile.in is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13# PARTICULAR PURPOSE.
14
15@SET_MAKE@
16
17
18VPATH = @srcdir@
19pkgdatadir = $(datadir)/@PACKAGE@
20pkglibdir = $(libdir)/@PACKAGE@
21pkgincludedir = $(includedir)/@PACKAGE@
22am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
23install_sh_DATA = $(install_sh) -c -m 644
24install_sh_PROGRAM = $(install_sh) -c
25install_sh_SCRIPT = $(install_sh) -c
26INSTALL_HEADER = $(INSTALL_DATA)
27transform = $(program_transform_name)
28NORMAL_INSTALL = :
29PRE_INSTALL = :
30POST_INSTALL = :
31NORMAL_UNINSTALL = :
32PRE_UNINSTALL = :
33POST_UNINSTALL = :
34build_triplet = @build@
35host_triplet = @host@
36target_triplet = @target@
37traplib_PROGRAMS = libode$(EXEEXT)
38@USE_SONAME_TRUE@am__append_1 = -Wl,-soname,@ODE_SONAME@
39@OPCODE_TRUE@am__append_2 = libOPCODE.a
40@OPCODE_TRUE@am__append_3 = $(libOPCODE_a_OBJECTS)
41@GIMPACT_TRUE@am__append_4 = libGIMPACT.a
42@GIMPACT_TRUE@am__append_5 = $(libGIMPACT_a_OBJECTS)
43
44###################################
45# G I M P A C T S T U F F
46###################################
47@GIMPACT_TRUE@am__append_6 = libGIMPACT.a
48@GIMPACT_TRUE@am__append_7 = collision_trimesh_gimpact.cpp \
49@GIMPACT_TRUE@ collision_trimesh_trimesh.cpp \
50@GIMPACT_TRUE@ collision_trimesh_sphere.cpp \
51@GIMPACT_TRUE@ collision_trimesh_ray.cpp \
52@GIMPACT_TRUE@ collision_trimesh_opcode.cpp \
53@GIMPACT_TRUE@ collision_trimesh_box.cpp \
54@GIMPACT_TRUE@ collision_trimesh_ccylinder.cpp \
55@GIMPACT_TRUE@ collision_trimesh_distance.cpp \
56@GIMPACT_TRUE@ collision_trimesh_internal.h \
57@GIMPACT_TRUE@ collision_cylinder_trimesh.cpp \
58@GIMPACT_TRUE@ collision_trimesh_plane.cpp
59@GIMPACT_TRUE@am__append_8 = libGIMPACT.a
60@GIMPACT_TRUE@am__append_9 = $(libGIMPACT_a_OBJECTS)
61@GIMPACT_TRUE@am__append_10 = -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
62@GIMPACT_TRUE@am__append_11 = -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
63
64#################################
65# O P C O D E S T U F F
66#################################
67@OPCODE_TRUE@am__append_12 = libOPCODE.a
68@OPCODE_TRUE@am__append_13 = libOPCODE.a
69@OPCODE_TRUE@am__append_14 = $(libOPCODE_a_OBJECTS)
70@OPCODE_TRUE@am__append_15 = -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
71@OPCODE_TRUE@am__append_16 = -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
72@OPCODE_TRUE@am__append_17 = collision_trimesh_trimesh.cpp \
73@OPCODE_TRUE@ collision_trimesh_sphere.cpp \
74@OPCODE_TRUE@ collision_trimesh_ray.cpp \
75@OPCODE_TRUE@ collision_trimesh_opcode.cpp \
76@OPCODE_TRUE@ collision_trimesh_box.cpp \
77@OPCODE_TRUE@ collision_trimesh_ccylinder.cpp \
78@OPCODE_TRUE@ collision_trimesh_distance.cpp \
79@OPCODE_TRUE@ collision_trimesh_internal.h \
80@OPCODE_TRUE@ collision_cylinder_trimesh.cpp \
81@OPCODE_TRUE@ collision_trimesh_plane.cpp
82
83subdir = ode/src
84DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
85ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
86am__aclocal_m4_deps = $(top_srcdir)/configure.in
87am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
88 $(ACLOCAL_M4)
89mkinstalldirs = $(install_sh) -d
90CONFIG_HEADER = $(top_builddir)/include/ode/config.h
91CONFIG_CLEAN_FILES =
92am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
93am__vpath_adj = case $$p in \
94 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
95 *) f=$$p;; \
96 esac;
97am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
98am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(traplibdir)"
99libLIBRARIES_INSTALL = $(INSTALL_DATA)
100LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES)
101AR = ar
102ARFLAGS = cru
103libGIMPACT_a_AR = $(AR) $(ARFLAGS)
104libGIMPACT_a_LIBADD =
105am__libGIMPACT_a_SOURCES_DIST = \
106 @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
107 @TOPDIR@/GIMPACT/src/gim_contact.cpp \
108 @TOPDIR@/GIMPACT/src/gim_math.cpp \
109 @TOPDIR@/GIMPACT/src/gim_memory.cpp \
110 @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
111 @TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
112 @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
113 @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
114 @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
115 @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
116 @TOPDIR@/GIMPACT/src/gimpact.cpp
117@GIMPACT_TRUE@am_libGIMPACT_a_OBJECTS = \
118@GIMPACT_TRUE@ libGIMPACT_a-gim_boxpruning.$(OBJEXT) \
119@GIMPACT_TRUE@ libGIMPACT_a-gim_contact.$(OBJEXT) \
120@GIMPACT_TRUE@ libGIMPACT_a-gim_math.$(OBJEXT) \
121@GIMPACT_TRUE@ libGIMPACT_a-gim_memory.$(OBJEXT) \
122@GIMPACT_TRUE@ libGIMPACT_a-gim_tri_tri_overlap.$(OBJEXT) \
123@GIMPACT_TRUE@ libGIMPACT_a-gim_trimesh.$(OBJEXT) \
124@GIMPACT_TRUE@ libGIMPACT_a-gim_trimesh_capsule_collision.$(OBJEXT) \
125@GIMPACT_TRUE@ libGIMPACT_a-gim_trimesh_ray_collision.$(OBJEXT) \
126@GIMPACT_TRUE@ libGIMPACT_a-gim_trimesh_sphere_collision.$(OBJEXT) \
127@GIMPACT_TRUE@ libGIMPACT_a-gim_trimesh_trimesh_collision.$(OBJEXT) \
128@GIMPACT_TRUE@ libGIMPACT_a-gimpact.$(OBJEXT)
129libGIMPACT_a_OBJECTS = $(am_libGIMPACT_a_OBJECTS)
130libOPCODE_a_AR = $(AR) $(ARFLAGS)
131libOPCODE_a_LIBADD =
132am__libOPCODE_a_SOURCES_DIST = @TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
133 @TOPDIR@/OPCODE/OPC_AABBTree.cpp \
134 @TOPDIR@/OPCODE/OPC_BaseModel.cpp \
135 @TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
136 @TOPDIR@/OPCODE/OPC_Collider.cpp \
137 @TOPDIR@/OPCODE/OPC_Common.cpp \
138 @TOPDIR@/OPCODE/OPC_HybridModel.cpp \
139 @TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
140 @TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
141 @TOPDIR@/OPCODE/OPC_Model.cpp \
142 @TOPDIR@/OPCODE/OPC_OBBCollider.cpp @TOPDIR@/OPCODE/Opcode.cpp \
143 @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
144 @TOPDIR@/OPCODE/OPC_Picking.cpp \
145 @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
146 @TOPDIR@/OPCODE/OPC_RayCollider.cpp \
147 @TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
148 @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
149 @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
150 @TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
151 @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
152 @TOPDIR@/OPCODE/Ice/IceAABB.cpp \
153 @TOPDIR@/OPCODE/Ice/IceContainer.cpp \
154 @TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
155 @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
156 @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
157 @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
158 @TOPDIR@/OPCODE/Ice/IceOBB.cpp \
159 @TOPDIR@/OPCODE/Ice/IcePlane.cpp \
160 @TOPDIR@/OPCODE/Ice/IcePoint.cpp \
161 @TOPDIR@/OPCODE/Ice/IceRandom.cpp \
162 @TOPDIR@/OPCODE/Ice/IceRay.cpp \
163 @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
164 @TOPDIR@/OPCODE/Ice/IceSegment.cpp \
165 @TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
166 @TOPDIR@/OPCODE/Ice/IceUtils.cpp
167@OPCODE_TRUE@am_libOPCODE_a_OBJECTS = \
168@OPCODE_TRUE@ libOPCODE_a-OPC_AABBCollider.$(OBJEXT) \
169@OPCODE_TRUE@ libOPCODE_a-OPC_AABBTree.$(OBJEXT) \
170@OPCODE_TRUE@ libOPCODE_a-OPC_BaseModel.$(OBJEXT) \
171@OPCODE_TRUE@ libOPCODE_a-OPC_BoxPruning.$(OBJEXT) \
172@OPCODE_TRUE@ libOPCODE_a-OPC_Collider.$(OBJEXT) \
173@OPCODE_TRUE@ libOPCODE_a-OPC_Common.$(OBJEXT) \
174@OPCODE_TRUE@ libOPCODE_a-OPC_HybridModel.$(OBJEXT) \
175@OPCODE_TRUE@ libOPCODE_a-OPC_LSSCollider.$(OBJEXT) \
176@OPCODE_TRUE@ libOPCODE_a-OPC_MeshInterface.$(OBJEXT) \
177@OPCODE_TRUE@ libOPCODE_a-OPC_Model.$(OBJEXT) \
178@OPCODE_TRUE@ libOPCODE_a-OPC_OBBCollider.$(OBJEXT) \
179@OPCODE_TRUE@ libOPCODE_a-Opcode.$(OBJEXT) \
180@OPCODE_TRUE@ libOPCODE_a-OPC_OptimizedTree.$(OBJEXT) \
181@OPCODE_TRUE@ libOPCODE_a-OPC_Picking.$(OBJEXT) \
182@OPCODE_TRUE@ libOPCODE_a-OPC_PlanesCollider.$(OBJEXT) \
183@OPCODE_TRUE@ libOPCODE_a-OPC_RayCollider.$(OBJEXT) \
184@OPCODE_TRUE@ libOPCODE_a-OPC_SphereCollider.$(OBJEXT) \
185@OPCODE_TRUE@ libOPCODE_a-OPC_SweepAndPrune.$(OBJEXT) \
186@OPCODE_TRUE@ libOPCODE_a-OPC_TreeBuilders.$(OBJEXT) \
187@OPCODE_TRUE@ libOPCODE_a-OPC_TreeCollider.$(OBJEXT) \
188@OPCODE_TRUE@ libOPCODE_a-OPC_VolumeCollider.$(OBJEXT) \
189@OPCODE_TRUE@ libOPCODE_a-IceAABB.$(OBJEXT) \
190@OPCODE_TRUE@ libOPCODE_a-IceContainer.$(OBJEXT) \
191@OPCODE_TRUE@ libOPCODE_a-IceHPoint.$(OBJEXT) \
192@OPCODE_TRUE@ libOPCODE_a-IceIndexedTriangle.$(OBJEXT) \
193@OPCODE_TRUE@ libOPCODE_a-IceMatrix3x3.$(OBJEXT) \
194@OPCODE_TRUE@ libOPCODE_a-IceMatrix4x4.$(OBJEXT) \
195@OPCODE_TRUE@ libOPCODE_a-IceOBB.$(OBJEXT) \
196@OPCODE_TRUE@ libOPCODE_a-IcePlane.$(OBJEXT) \
197@OPCODE_TRUE@ libOPCODE_a-IcePoint.$(OBJEXT) \
198@OPCODE_TRUE@ libOPCODE_a-IceRandom.$(OBJEXT) \
199@OPCODE_TRUE@ libOPCODE_a-IceRay.$(OBJEXT) \
200@OPCODE_TRUE@ libOPCODE_a-IceRevisitedRadix.$(OBJEXT) \
201@OPCODE_TRUE@ libOPCODE_a-IceSegment.$(OBJEXT) \
202@OPCODE_TRUE@ libOPCODE_a-IceTriangle.$(OBJEXT) \
203@OPCODE_TRUE@ libOPCODE_a-IceUtils.$(OBJEXT)
204libOPCODE_a_OBJECTS = $(am_libOPCODE_a_OBJECTS)
205libfast_a_AR = $(AR) $(ARFLAGS)
206libfast_a_LIBADD =
207am_libfast_a_OBJECTS = libfast_a-fastldlt.$(OBJEXT) \
208 libfast_a-fastltsolve.$(OBJEXT) libfast_a-fastdot.$(OBJEXT) \
209 libfast_a-fastlsolve.$(OBJEXT)
210libfast_a_OBJECTS = $(am_libfast_a_OBJECTS)
211libode_a_AR = $(AR) $(ARFLAGS)
212am__libode_a_SOURCES_DIST = objects.h obstack.cpp collision_util.cpp \
213 obstack.h array.cpp collision_util.h ode.cpp array.h error.cpp \
214 odemath.cpp collision_kernel.cpp export-dif.cpp quickstep.cpp \
215 collision_kernel.h quickstep.h collision_quadtreespace.cpp \
216 rotation.cpp collision_space.cpp collision_space_internal.h \
217 collision_cylinder_box.cpp collision_cylinder_sphere.cpp \
218 collision_cylinder_plane.cpp sphere.cpp box.cpp capsule.cpp \
219 plane.cpp ray.cpp cylinder.cpp convex.cpp joint.cpp stack.h \
220 collision_std.h joint.h step.cpp collision_transform.cpp \
221 lcp.cpp step.h collision_transform.h lcp.h stepfast.cpp \
222 mass.cpp testing.cpp mat.cpp testing.h mat.h timer.cpp \
223 matrix.cpp util.cpp memory.cpp util.h misc.cpp heightfield.cpp \
224 heightfield.h collision_trimesh_gimpact.cpp \
225 collision_trimesh_trimesh.cpp collision_trimesh_sphere.cpp \
226 collision_trimesh_ray.cpp collision_trimesh_opcode.cpp \
227 collision_trimesh_box.cpp collision_trimesh_ccylinder.cpp \
228 collision_trimesh_distance.cpp collision_trimesh_internal.h \
229 collision_cylinder_trimesh.cpp collision_trimesh_plane.cpp
230@GIMPACT_TRUE@am__objects_1 = \
231@GIMPACT_TRUE@ libode_a-collision_trimesh_gimpact.$(OBJEXT) \
232@GIMPACT_TRUE@ libode_a-collision_trimesh_trimesh.$(OBJEXT) \
233@GIMPACT_TRUE@ libode_a-collision_trimesh_sphere.$(OBJEXT) \
234@GIMPACT_TRUE@ libode_a-collision_trimesh_ray.$(OBJEXT) \
235@GIMPACT_TRUE@ libode_a-collision_trimesh_opcode.$(OBJEXT) \
236@GIMPACT_TRUE@ libode_a-collision_trimesh_box.$(OBJEXT) \
237@GIMPACT_TRUE@ libode_a-collision_trimesh_ccylinder.$(OBJEXT) \
238@GIMPACT_TRUE@ libode_a-collision_trimesh_distance.$(OBJEXT) \
239@GIMPACT_TRUE@ libode_a-collision_cylinder_trimesh.$(OBJEXT) \
240@GIMPACT_TRUE@ libode_a-collision_trimesh_plane.$(OBJEXT)
241@OPCODE_TRUE@am__objects_2 = \
242@OPCODE_TRUE@ libode_a-collision_trimesh_trimesh.$(OBJEXT) \
243@OPCODE_TRUE@ libode_a-collision_trimesh_sphere.$(OBJEXT) \
244@OPCODE_TRUE@ libode_a-collision_trimesh_ray.$(OBJEXT) \
245@OPCODE_TRUE@ libode_a-collision_trimesh_opcode.$(OBJEXT) \
246@OPCODE_TRUE@ libode_a-collision_trimesh_box.$(OBJEXT) \
247@OPCODE_TRUE@ libode_a-collision_trimesh_ccylinder.$(OBJEXT) \
248@OPCODE_TRUE@ libode_a-collision_trimesh_distance.$(OBJEXT) \
249@OPCODE_TRUE@ libode_a-collision_cylinder_trimesh.$(OBJEXT) \
250@OPCODE_TRUE@ libode_a-collision_trimesh_plane.$(OBJEXT)
251am_libode_a_OBJECTS = libode_a-obstack.$(OBJEXT) \
252 libode_a-collision_util.$(OBJEXT) libode_a-array.$(OBJEXT) \
253 libode_a-ode.$(OBJEXT) libode_a-error.$(OBJEXT) \
254 libode_a-odemath.$(OBJEXT) libode_a-collision_kernel.$(OBJEXT) \
255 libode_a-export-dif.$(OBJEXT) libode_a-quickstep.$(OBJEXT) \
256 libode_a-collision_quadtreespace.$(OBJEXT) \
257 libode_a-rotation.$(OBJEXT) libode_a-collision_space.$(OBJEXT) \
258 libode_a-collision_cylinder_box.$(OBJEXT) \
259 libode_a-collision_cylinder_sphere.$(OBJEXT) \
260 libode_a-collision_cylinder_plane.$(OBJEXT) \
261 libode_a-sphere.$(OBJEXT) libode_a-box.$(OBJEXT) \
262 libode_a-capsule.$(OBJEXT) libode_a-plane.$(OBJEXT) \
263 libode_a-ray.$(OBJEXT) libode_a-cylinder.$(OBJEXT) \
264 libode_a-convex.$(OBJEXT) libode_a-joint.$(OBJEXT) \
265 libode_a-step.$(OBJEXT) libode_a-collision_transform.$(OBJEXT) \
266 libode_a-lcp.$(OBJEXT) libode_a-stepfast.$(OBJEXT) \
267 libode_a-mass.$(OBJEXT) libode_a-testing.$(OBJEXT) \
268 libode_a-mat.$(OBJEXT) libode_a-timer.$(OBJEXT) \
269 libode_a-matrix.$(OBJEXT) libode_a-util.$(OBJEXT) \
270 libode_a-memory.$(OBJEXT) libode_a-misc.$(OBJEXT) \
271 libode_a-heightfield.$(OBJEXT) $(am__objects_1) \
272 $(am__objects_2)
273libode_a_OBJECTS = $(am_libode_a_OBJECTS)
274traplibPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
275PROGRAMS = $(traplib_PROGRAMS)
276am_libode_OBJECTS =
277libode_OBJECTS = $(am_libode_OBJECTS)
278libode_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libode_LDFLAGS) \
279 $(LDFLAGS) -o $@
280DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
281depcomp = $(SHELL) $(top_srcdir)/depcomp
282am__depfiles_maybe = depfiles
283COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
284 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
285CCLD = $(CC)
286LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
287CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
288 $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
289CXXLD = $(CXX)
290CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
291 -o $@
292SOURCES = $(libGIMPACT_a_SOURCES) $(libOPCODE_a_SOURCES) \
293 $(libfast_a_SOURCES) $(libode_a_SOURCES) $(libode_SOURCES)
294DIST_SOURCES = $(am__libGIMPACT_a_SOURCES_DIST) \
295 $(am__libOPCODE_a_SOURCES_DIST) $(libfast_a_SOURCES) \
296 $(am__libode_a_SOURCES_DIST) $(libode_SOURCES)
297ETAGS = etags
298CTAGS = ctags
299DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
300ACLOCAL = @ACLOCAL@
301ALLOCA = @ALLOCA@
302AMTAR = @AMTAR@
303ARCHFLAGS = @ARCHFLAGS@
304AUTOCONF = @AUTOCONF@
305AUTOHEADER = @AUTOHEADER@
306AUTOMAKE = @AUTOMAKE@
307AWK = @AWK@
308CC = @CC@
309CCDEPMODE = @CCDEPMODE@
310CFLAGS = @CFLAGS@
311CPP = @CPP@
312CPPFLAGS = @CPPFLAGS@
313CXX = @CXX@
314CXXDEPMODE = @CXXDEPMODE@
315CXXFLAGS = @CXXFLAGS@
316CYGPATH_W = @CYGPATH_W@
317DEFS = @DEFS@
318DEPDIR = @DEPDIR@
319DRAWSTUFF = @DRAWSTUFF@
320ECHO_C = @ECHO_C@
321ECHO_N = @ECHO_N@
322ECHO_T = @ECHO_T@
323EGREP = @EGREP@
324EXEEXT = @so_ext@
325GL_LIBS = @GL_LIBS@
326GREP = @GREP@
327INSTALL = @INSTALL@
328INSTALL_DATA = @INSTALL_DATA@
329INSTALL_PROGRAM = @INSTALL_PROGRAM@
330INSTALL_SCRIPT = @INSTALL_SCRIPT@
331INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
332LDFLAGS = @LDFLAGS@
333LIBOBJS = @LIBOBJS@
334LIBS = @LIBS@
335LTLIBOBJS = @LTLIBOBJS@
336MAKEINFO = @MAKEINFO@
337MKDIR_P = @MKDIR_P@
338OBJEXT = @OBJEXT@
339ODE_AGE = @ODE_AGE@
340ODE_CURRENT = @ODE_CURRENT@
341ODE_RELEASE = @ODE_RELEASE@
342ODE_REVISION = @ODE_REVISION@
343ODE_SONAME = @ODE_SONAME@
344PACKAGE = @PACKAGE@
345PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
346PACKAGE_NAME = @PACKAGE_NAME@
347PACKAGE_STRING = @PACKAGE_STRING@
348PACKAGE_TARNAME = @PACKAGE_TARNAME@
349PACKAGE_VERSION = @PACKAGE_VERSION@
350PATH_SEPARATOR = @PATH_SEPARATOR@
351RANLIB = @RANLIB@
352SET_MAKE = @SET_MAKE@
353SHARED_LDFLAGS = @SHARED_LDFLAGS@
354SHELL = @SHELL@
355STRIP = @STRIP@
356TOPDIR = @TOPDIR@
357VERSION = @VERSION@
358WINDRES = @WINDRES@
359XMKMF = @XMKMF@
360X_CFLAGS = @X_CFLAGS@
361X_EXTRA_LIBS = @X_EXTRA_LIBS@
362X_LIBS = @X_LIBS@
363X_PRE_LIBS = @X_PRE_LIBS@
364abs_builddir = @abs_builddir@
365abs_srcdir = @abs_srcdir@
366abs_top_builddir = @abs_top_builddir@
367abs_top_srcdir = @abs_top_srcdir@
368ac_ct_CC = @ac_ct_CC@
369ac_ct_CXX = @ac_ct_CXX@
370ac_ct_WINDRES = @ac_ct_WINDRES@
371am__include = @am__include@
372am__leading_dot = @am__leading_dot@
373am__quote = @am__quote@
374am__tar = @am__tar@
375am__untar = @am__untar@
376bindir = @bindir@
377build = @build@
378build_alias = @build_alias@
379build_cpu = @build_cpu@
380build_os = @build_os@
381build_vendor = @build_vendor@
382builddir = @builddir@
383datadir = @datadir@
384datarootdir = @datarootdir@
385docdir = @docdir@
386dvidir = @dvidir@
387exec_prefix = @exec_prefix@
388host = @host@
389host_alias = @host_alias@
390host_cpu = @host_cpu@
391host_os = @host_os@
392host_vendor = @host_vendor@
393htmldir = @htmldir@
394includedir = @includedir@
395infodir = @infodir@
396install_sh = @install_sh@
397libdir = @libdir@
398libexecdir = @libexecdir@
399localedir = @localedir@
400localstatedir = @localstatedir@
401mandir = @mandir@
402mkdir_p = @mkdir_p@
403oldincludedir = @oldincludedir@
404pdfdir = @pdfdir@
405prefix = @prefix@
406program_transform_name = @program_transform_name@
407psdir = @psdir@
408sbindir = @sbindir@
409sharedstatedir = @sharedstatedir@
410so_ext = @so_ext@
411srcdir = @srcdir@
412sysconfdir = @sysconfdir@
413target = @target@
414target_alias = @target_alias@
415target_cpu = @target_cpu@
416target_os = @target_os@
417target_vendor = @target_vendor@
418top_builddir = @top_builddir@
419top_srcdir = @top_srcdir@
420AM_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include \
421 -I$(top_builddir)/include $(am__append_10) $(am__append_15)
422AM_CPPFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
423AM_CFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include \
424 -I$(top_builddir)/include $(am__append_11) $(am__append_16)
425lib_LIBRARIES = libode.a
426libode_a_CPPFLAGS = -O2 -fPIC
427
428# Fake an executable in order to get a shared library
429# Note the elegant and cunning way to trick Autotools to install a program
430# in a lib directory. --Rodrigo
431traplibdir = $(libdir)
432libode_SOURCES =
433libode_DEPENDENCIES = libfast.a libode.a $(am__append_2) \
434 $(am__append_4)
435libode_LDFLAGS = @SHARED_LDFLAGS@ $(am__append_1)
436libode_LDADD = $(libode_a_OBJECTS) $(libfast_a_OBJECTS) \
437 $(am__append_3) $(am__append_5)
438
439# convenience library to simulate per object cflags
440noinst_LIBRARIES = libfast.a $(am__append_6) $(am__append_12)
441libfast_a_CFLAGS = -O1 -fPIC
442libfast_a_SOURCES = fastldlt.c fastltsolve.c fastdot.c fastlsolve.c
443libode_a_DEPENDENCIES = libfast.a $(am__append_8) $(am__append_13)
444libode_a_LIBADD = $(libfast_a_OBJECTS) $(am__append_9) \
445 $(am__append_14)
446libode_a_SOURCES = objects.h obstack.cpp collision_util.cpp obstack.h \
447 array.cpp collision_util.h ode.cpp array.h error.cpp \
448 odemath.cpp collision_kernel.cpp export-dif.cpp quickstep.cpp \
449 collision_kernel.h quickstep.h collision_quadtreespace.cpp \
450 rotation.cpp collision_space.cpp collision_space_internal.h \
451 collision_cylinder_box.cpp collision_cylinder_sphere.cpp \
452 collision_cylinder_plane.cpp sphere.cpp box.cpp capsule.cpp \
453 plane.cpp ray.cpp cylinder.cpp convex.cpp joint.cpp stack.h \
454 collision_std.h joint.h step.cpp collision_transform.cpp \
455 lcp.cpp step.h collision_transform.h lcp.h stepfast.cpp \
456 mass.cpp testing.cpp mat.cpp testing.h mat.h timer.cpp \
457 matrix.cpp util.cpp memory.cpp util.h misc.cpp heightfield.cpp \
458 heightfield.h $(am__append_7) $(am__append_17)
459@GIMPACT_TRUE@libGIMPACT_a_CPPFLAGS = -O2 -fno-strict-aliasing -fPIC
460@GIMPACT_TRUE@libGIMPACT_a_SOURCES = \
461@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
462@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_contact.cpp \
463@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_math.cpp \
464@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_memory.cpp \
465@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
466@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
467@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
468@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
469@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
470@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
471@GIMPACT_TRUE@ @TOPDIR@/GIMPACT/src/gimpact.cpp
472
473@OPCODE_TRUE@libOPCODE_a_CPPFLAGS = -O2 -fno-strict-aliasing -fPIC
474@OPCODE_TRUE@libOPCODE_a_SOURCES = @TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
475@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_AABBTree.cpp \
476@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_BaseModel.cpp \
477@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
478@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_Collider.cpp \
479@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_Common.cpp \
480@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_HybridModel.cpp \
481@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
482@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
483@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_Model.cpp \
484@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_OBBCollider.cpp \
485@OPCODE_TRUE@ @TOPDIR@/OPCODE/Opcode.cpp \
486@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
487@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_Picking.cpp \
488@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
489@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_RayCollider.cpp \
490@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
491@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
492@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
493@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
494@OPCODE_TRUE@ @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
495@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceAABB.cpp \
496@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceContainer.cpp \
497@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
498@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
499@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
500@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
501@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceOBB.cpp \
502@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IcePlane.cpp \
503@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IcePoint.cpp \
504@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceRandom.cpp \
505@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceRay.cpp \
506@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
507@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceSegment.cpp \
508@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
509@OPCODE_TRUE@ @TOPDIR@/OPCODE/Ice/IceUtils.cpp
510
511all: all-am
512
513.SUFFIXES:
514.SUFFIXES: .c .cpp .o .obj
515$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
516 @for dep in $?; do \
517 case '$(am__configure_deps)' in \
518 *$$dep*) \
519 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
520 && exit 0; \
521 exit 1;; \
522 esac; \
523 done; \
524 echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/src/Makefile'; \
525 cd $(top_srcdir) && \
526 $(AUTOMAKE) --foreign ode/src/Makefile
527.PRECIOUS: Makefile
528Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
529 @case '$?' in \
530 *config.status*) \
531 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
532 *) \
533 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
534 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
535 esac;
536
537$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
538 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
539
540$(top_srcdir)/configure: $(am__configure_deps)
541 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
542$(ACLOCAL_M4): $(am__aclocal_m4_deps)
543 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
544install-libLIBRARIES: $(lib_LIBRARIES)
545 @$(NORMAL_INSTALL)
546 test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
547 @list='$(lib_LIBRARIES)'; for p in $$list; do \
548 if test -f $$p; then \
549 f=$(am__strip_dir) \
550 echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
551 $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
552 else :; fi; \
553 done
554 @$(POST_INSTALL)
555 @list='$(lib_LIBRARIES)'; for p in $$list; do \
556 if test -f $$p; then \
557 p=$(am__strip_dir) \
558 echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
559 $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
560 else :; fi; \
561 done
562
563uninstall-libLIBRARIES:
564 @$(NORMAL_UNINSTALL)
565 @list='$(lib_LIBRARIES)'; for p in $$list; do \
566 p=$(am__strip_dir) \
567 echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
568 rm -f "$(DESTDIR)$(libdir)/$$p"; \
569 done
570
571clean-libLIBRARIES:
572 -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
573
574clean-noinstLIBRARIES:
575 -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
576libGIMPACT.a: $(libGIMPACT_a_OBJECTS) $(libGIMPACT_a_DEPENDENCIES)
577 -rm -f libGIMPACT.a
578 $(libGIMPACT_a_AR) libGIMPACT.a $(libGIMPACT_a_OBJECTS) $(libGIMPACT_a_LIBADD)
579 $(RANLIB) libGIMPACT.a
580libOPCODE.a: $(libOPCODE_a_OBJECTS) $(libOPCODE_a_DEPENDENCIES)
581 -rm -f libOPCODE.a
582 $(libOPCODE_a_AR) libOPCODE.a $(libOPCODE_a_OBJECTS) $(libOPCODE_a_LIBADD)
583 $(RANLIB) libOPCODE.a
584libfast.a: $(libfast_a_OBJECTS) $(libfast_a_DEPENDENCIES)
585 -rm -f libfast.a
586 $(libfast_a_AR) libfast.a $(libfast_a_OBJECTS) $(libfast_a_LIBADD)
587 $(RANLIB) libfast.a
588libode.a: $(libode_a_OBJECTS) $(libode_a_DEPENDENCIES)
589 -rm -f libode.a
590 $(libode_a_AR) libode.a $(libode_a_OBJECTS) $(libode_a_LIBADD)
591 $(RANLIB) libode.a
592install-traplibPROGRAMS: $(traplib_PROGRAMS)
593 @$(NORMAL_INSTALL)
594 test -z "$(traplibdir)" || $(MKDIR_P) "$(DESTDIR)$(traplibdir)"
595 @list='$(traplib_PROGRAMS)'; for p in $$list; do \
596 p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
597 if test -f $$p \
598 ; then \
599 f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
600 echo " $(INSTALL_PROGRAM_ENV) $(traplibPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(traplibdir)/$$f'"; \
601 $(INSTALL_PROGRAM_ENV) $(traplibPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(traplibdir)/$$f" || exit 1; \
602 else :; fi; \
603 done
604
605uninstall-traplibPROGRAMS:
606 @$(NORMAL_UNINSTALL)
607 @list='$(traplib_PROGRAMS)'; for p in $$list; do \
608 f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
609 echo " rm -f '$(DESTDIR)$(traplibdir)/$$f'"; \
610 rm -f "$(DESTDIR)$(traplibdir)/$$f"; \
611 done
612
613clean-traplibPROGRAMS:
614 -test -z "$(traplib_PROGRAMS)" || rm -f $(traplib_PROGRAMS)
615libode$(EXEEXT): $(libode_OBJECTS) $(libode_DEPENDENCIES)
616 @rm -f libode$(EXEEXT)
617 $(libode_LINK) $(libode_OBJECTS) $(libode_LDADD) $(LIBS)
618
619mostlyclean-compile:
620 -rm -f *.$(OBJEXT)
621
622distclean-compile:
623 -rm -f *.tab.c
624
625@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po@am__quote@
626@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_contact.Po@am__quote@
627@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_math.Po@am__quote@
628@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_memory.Po@am__quote@
629@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po@am__quote@
630@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh.Po@am__quote@
631@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po@am__quote@
632@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po@am__quote@
633@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po@am__quote@
634@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po@am__quote@
635@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gimpact.Po@am__quote@
636@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceAABB.Po@am__quote@
637@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceContainer.Po@am__quote@
638@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceHPoint.Po@am__quote@
639@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po@am__quote@
640@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po@am__quote@
641@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po@am__quote@
642@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceOBB.Po@am__quote@
643@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IcePlane.Po@am__quote@
644@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IcePoint.Po@am__quote@
645@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRandom.Po@am__quote@
646@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRay.Po@am__quote@
647@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po@am__quote@
648@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceSegment.Po@am__quote@
649@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceTriangle.Po@am__quote@
650@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceUtils.Po@am__quote@
651@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po@am__quote@
652@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po@am__quote@
653@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po@am__quote@
654@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po@am__quote@
655@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Collider.Po@am__quote@
656@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Common.Po@am__quote@
657@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po@am__quote@
658@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po@am__quote@
659@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po@am__quote@
660@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Model.Po@am__quote@
661@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po@am__quote@
662@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po@am__quote@
663@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Picking.Po@am__quote@
664@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po@am__quote@
665@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po@am__quote@
666@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po@am__quote@
667@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po@am__quote@
668@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po@am__quote@
669@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po@am__quote@
670@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po@am__quote@
671@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-Opcode.Po@am__quote@
672@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastdot.Po@am__quote@
673@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastldlt.Po@am__quote@
674@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastlsolve.Po@am__quote@
675@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastltsolve.Po@am__quote@
676@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-array.Po@am__quote@
677@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-box.Po@am__quote@
678@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-capsule.Po@am__quote@
679@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_box.Po@am__quote@
680@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_plane.Po@am__quote@
681@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_sphere.Po@am__quote@
682@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_trimesh.Po@am__quote@
683@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_kernel.Po@am__quote@
684@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_quadtreespace.Po@am__quote@
685@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_space.Po@am__quote@
686@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_transform.Po@am__quote@
687@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_box.Po@am__quote@
688@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po@am__quote@
689@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_distance.Po@am__quote@
690@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_gimpact.Po@am__quote@
691@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_opcode.Po@am__quote@
692@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_plane.Po@am__quote@
693@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_ray.Po@am__quote@
694@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_sphere.Po@am__quote@
695@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_trimesh.Po@am__quote@
696@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_util.Po@am__quote@
697@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-convex.Po@am__quote@
698@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-cylinder.Po@am__quote@
699@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-error.Po@am__quote@
700@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-export-dif.Po@am__quote@
701@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-heightfield.Po@am__quote@
702@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-joint.Po@am__quote@
703@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-lcp.Po@am__quote@
704@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-mass.Po@am__quote@
705@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-mat.Po@am__quote@
706@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-matrix.Po@am__quote@
707@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-memory.Po@am__quote@
708@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-misc.Po@am__quote@
709@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-obstack.Po@am__quote@
710@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-ode.Po@am__quote@
711@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-odemath.Po@am__quote@
712@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-plane.Po@am__quote@
713@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-quickstep.Po@am__quote@
714@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-ray.Po@am__quote@
715@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-rotation.Po@am__quote@
716@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-sphere.Po@am__quote@
717@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-step.Po@am__quote@
718@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-stepfast.Po@am__quote@
719@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-testing.Po@am__quote@
720@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-timer.Po@am__quote@
721@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-util.Po@am__quote@
722
723.c.o:
724@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
725@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
726@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
727@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
728@am__fastdepCC_FALSE@ $(COMPILE) -c $<
729
730.c.obj:
731@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
732@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
733@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
734@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
735@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
736
737libfast_a-fastldlt.o: fastldlt.c
738@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
739@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastldlt.Tpo $(DEPDIR)/libfast_a-fastldlt.Po
740@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastldlt.c' object='libfast_a-fastldlt.o' libtool=no @AMDEPBACKSLASH@
741@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
742@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
743
744libfast_a-fastldlt.obj: fastldlt.c
745@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`
746@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastldlt.Tpo $(DEPDIR)/libfast_a-fastldlt.Po
747@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastldlt.c' object='libfast_a-fastldlt.obj' libtool=no @AMDEPBACKSLASH@
748@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
749@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`
750
751libfast_a-fastltsolve.o: fastltsolve.c
752@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
753@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastltsolve.Tpo $(DEPDIR)/libfast_a-fastltsolve.Po
754@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastltsolve.c' object='libfast_a-fastltsolve.o' libtool=no @AMDEPBACKSLASH@
755@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
756@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
757
758libfast_a-fastltsolve.obj: fastltsolve.c
759@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`
760@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastltsolve.Tpo $(DEPDIR)/libfast_a-fastltsolve.Po
761@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastltsolve.c' object='libfast_a-fastltsolve.obj' libtool=no @AMDEPBACKSLASH@
762@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
763@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`
764
765libfast_a-fastdot.o: fastdot.c
766@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
767@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastdot.Tpo $(DEPDIR)/libfast_a-fastdot.Po
768@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastdot.c' object='libfast_a-fastdot.o' libtool=no @AMDEPBACKSLASH@
769@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
770@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
771
772libfast_a-fastdot.obj: fastdot.c
773@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`
774@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastdot.Tpo $(DEPDIR)/libfast_a-fastdot.Po
775@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastdot.c' object='libfast_a-fastdot.obj' libtool=no @AMDEPBACKSLASH@
776@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
777@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`
778
779libfast_a-fastlsolve.o: fastlsolve.c
780@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
781@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastlsolve.Tpo $(DEPDIR)/libfast_a-fastlsolve.Po
782@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastlsolve.c' object='libfast_a-fastlsolve.o' libtool=no @AMDEPBACKSLASH@
783@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
784@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
785
786libfast_a-fastlsolve.obj: fastlsolve.c
787@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`
788@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfast_a-fastlsolve.Tpo $(DEPDIR)/libfast_a-fastlsolve.Po
789@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fastlsolve.c' object='libfast_a-fastlsolve.obj' libtool=no @AMDEPBACKSLASH@
790@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
791@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`
792
793.cpp.o:
794@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
795@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
796@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
797@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
798@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
799
800.cpp.obj:
801@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
802@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
803@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
804@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
805@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
806
807libGIMPACT_a-gim_boxpruning.o: @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
808@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
809@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po
810@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' object='libGIMPACT_a-gim_boxpruning.o' libtool=no @AMDEPBACKSLASH@
811@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
812@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
813
814libGIMPACT_a-gim_boxpruning.obj: @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
815@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`
816@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po
817@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' object='libGIMPACT_a-gim_boxpruning.obj' libtool=no @AMDEPBACKSLASH@
818@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
819@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`
820
821libGIMPACT_a-gim_contact.o: @TOPDIR@/GIMPACT/src/gim_contact.cpp
822@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
823@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo $(DEPDIR)/libGIMPACT_a-gim_contact.Po
824@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_contact.cpp' object='libGIMPACT_a-gim_contact.o' libtool=no @AMDEPBACKSLASH@
825@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
826@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
827
828libGIMPACT_a-gim_contact.obj: @TOPDIR@/GIMPACT/src/gim_contact.cpp
829@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`
830@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo $(DEPDIR)/libGIMPACT_a-gim_contact.Po
831@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_contact.cpp' object='libGIMPACT_a-gim_contact.obj' libtool=no @AMDEPBACKSLASH@
832@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
833@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`
834
835libGIMPACT_a-gim_math.o: @TOPDIR@/GIMPACT/src/gim_math.cpp
836@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
837@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_math.Tpo $(DEPDIR)/libGIMPACT_a-gim_math.Po
838@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_math.cpp' object='libGIMPACT_a-gim_math.o' libtool=no @AMDEPBACKSLASH@
839@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
840@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
841
842libGIMPACT_a-gim_math.obj: @TOPDIR@/GIMPACT/src/gim_math.cpp
843@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`
844@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_math.Tpo $(DEPDIR)/libGIMPACT_a-gim_math.Po
845@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_math.cpp' object='libGIMPACT_a-gim_math.obj' libtool=no @AMDEPBACKSLASH@
846@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
847@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`
848
849libGIMPACT_a-gim_memory.o: @TOPDIR@/GIMPACT/src/gim_memory.cpp
850@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
851@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo $(DEPDIR)/libGIMPACT_a-gim_memory.Po
852@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_memory.cpp' object='libGIMPACT_a-gim_memory.o' libtool=no @AMDEPBACKSLASH@
853@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
854@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
855
856libGIMPACT_a-gim_memory.obj: @TOPDIR@/GIMPACT/src/gim_memory.cpp
857@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`
858@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo $(DEPDIR)/libGIMPACT_a-gim_memory.Po
859@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_memory.cpp' object='libGIMPACT_a-gim_memory.obj' libtool=no @AMDEPBACKSLASH@
860@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
861@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`
862
863libGIMPACT_a-gim_tri_tri_overlap.o: @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
864@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
865@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po
866@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@
867@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
868@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
869
870libGIMPACT_a-gim_tri_tri_overlap.obj: @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
871@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`
872@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po
873@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@
874@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
875@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`
876
877libGIMPACT_a-gim_trimesh.o: @TOPDIR@/GIMPACT/src/gim_trimesh.cpp
878@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
879@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh.Po
880@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' object='libGIMPACT_a-gim_trimesh.o' libtool=no @AMDEPBACKSLASH@
881@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
882@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
883
884libGIMPACT_a-gim_trimesh.obj: @TOPDIR@/GIMPACT/src/gim_trimesh.cpp
885@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`
886@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh.Po
887@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' object='libGIMPACT_a-gim_trimesh.obj' libtool=no @AMDEPBACKSLASH@
888@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
889@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`
890
891libGIMPACT_a-gim_trimesh_capsule_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
892@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
893@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po
894@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@
895@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
896@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
897
898libGIMPACT_a-gim_trimesh_capsule_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
899@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`
900@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po
901@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@
902@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
903@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`
904
905libGIMPACT_a-gim_trimesh_ray_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
906@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
907@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po
908@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@
909@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
910@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
911
912libGIMPACT_a-gim_trimesh_ray_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
913@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`
914@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po
915@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@
916@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
917@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`
918
919libGIMPACT_a-gim_trimesh_sphere_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
920@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
921@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po
922@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@
923@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
924@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
925
926libGIMPACT_a-gim_trimesh_sphere_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
927@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`
928@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po
929@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@
930@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
931@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`
932
933libGIMPACT_a-gim_trimesh_trimesh_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
934@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
935@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po
936@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@
937@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
938@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
939
940libGIMPACT_a-gim_trimesh_trimesh_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
941@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`
942@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po
943@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@
944@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
945@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`
946
947libGIMPACT_a-gimpact.o: @TOPDIR@/GIMPACT/src/gimpact.cpp
948@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
949@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gimpact.Tpo $(DEPDIR)/libGIMPACT_a-gimpact.Po
950@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gimpact.cpp' object='libGIMPACT_a-gimpact.o' libtool=no @AMDEPBACKSLASH@
951@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
952@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
953
954libGIMPACT_a-gimpact.obj: @TOPDIR@/GIMPACT/src/gimpact.cpp
955@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`
956@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libGIMPACT_a-gimpact.Tpo $(DEPDIR)/libGIMPACT_a-gimpact.Po
957@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/GIMPACT/src/gimpact.cpp' object='libGIMPACT_a-gimpact.obj' libtool=no @AMDEPBACKSLASH@
958@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
959@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`
960
961libOPCODE_a-OPC_AABBCollider.o: @TOPDIR@/OPCODE/OPC_AABBCollider.cpp
962@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
963@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po
964@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' object='libOPCODE_a-OPC_AABBCollider.o' libtool=no @AMDEPBACKSLASH@
965@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
966@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
967
968libOPCODE_a-OPC_AABBCollider.obj: @TOPDIR@/OPCODE/OPC_AABBCollider.cpp
969@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`
970@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po
971@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' object='libOPCODE_a-OPC_AABBCollider.obj' libtool=no @AMDEPBACKSLASH@
972@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
973@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`
974
975libOPCODE_a-OPC_AABBTree.o: @TOPDIR@/OPCODE/OPC_AABBTree.cpp
976@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
977@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po
978@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_AABBTree.cpp' object='libOPCODE_a-OPC_AABBTree.o' libtool=no @AMDEPBACKSLASH@
979@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
980@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
981
982libOPCODE_a-OPC_AABBTree.obj: @TOPDIR@/OPCODE/OPC_AABBTree.cpp
983@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`
984@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po
985@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_AABBTree.cpp' object='libOPCODE_a-OPC_AABBTree.obj' libtool=no @AMDEPBACKSLASH@
986@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
987@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`
988
989libOPCODE_a-OPC_BaseModel.o: @TOPDIR@/OPCODE/OPC_BaseModel.cpp
990@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
991@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po
992@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_BaseModel.cpp' object='libOPCODE_a-OPC_BaseModel.o' libtool=no @AMDEPBACKSLASH@
993@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
994@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
995
996libOPCODE_a-OPC_BaseModel.obj: @TOPDIR@/OPCODE/OPC_BaseModel.cpp
997@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`
998@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po
999@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_BaseModel.cpp' object='libOPCODE_a-OPC_BaseModel.obj' libtool=no @AMDEPBACKSLASH@
1000@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1001@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`
1002
1003libOPCODE_a-OPC_BoxPruning.o: @TOPDIR@/OPCODE/OPC_BoxPruning.cpp
1004@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
1005@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po
1006@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' object='libOPCODE_a-OPC_BoxPruning.o' libtool=no @AMDEPBACKSLASH@
1007@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1008@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
1009
1010libOPCODE_a-OPC_BoxPruning.obj: @TOPDIR@/OPCODE/OPC_BoxPruning.cpp
1011@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`
1012@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po
1013@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' object='libOPCODE_a-OPC_BoxPruning.obj' libtool=no @AMDEPBACKSLASH@
1014@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1015@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`
1016
1017libOPCODE_a-OPC_Collider.o: @TOPDIR@/OPCODE/OPC_Collider.cpp
1018@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
1019@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo $(DEPDIR)/libOPCODE_a-OPC_Collider.Po
1020@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Collider.cpp' object='libOPCODE_a-OPC_Collider.o' libtool=no @AMDEPBACKSLASH@
1021@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1022@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
1023
1024libOPCODE_a-OPC_Collider.obj: @TOPDIR@/OPCODE/OPC_Collider.cpp
1025@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`
1026@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo $(DEPDIR)/libOPCODE_a-OPC_Collider.Po
1027@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Collider.cpp' object='libOPCODE_a-OPC_Collider.obj' libtool=no @AMDEPBACKSLASH@
1028@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1029@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`
1030
1031libOPCODE_a-OPC_Common.o: @TOPDIR@/OPCODE/OPC_Common.cpp
1032@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
1033@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo $(DEPDIR)/libOPCODE_a-OPC_Common.Po
1034@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Common.cpp' object='libOPCODE_a-OPC_Common.o' libtool=no @AMDEPBACKSLASH@
1035@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1036@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
1037
1038libOPCODE_a-OPC_Common.obj: @TOPDIR@/OPCODE/OPC_Common.cpp
1039@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`
1040@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo $(DEPDIR)/libOPCODE_a-OPC_Common.Po
1041@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Common.cpp' object='libOPCODE_a-OPC_Common.obj' libtool=no @AMDEPBACKSLASH@
1042@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1043@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`
1044
1045libOPCODE_a-OPC_HybridModel.o: @TOPDIR@/OPCODE/OPC_HybridModel.cpp
1046@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
1047@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po
1048@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_HybridModel.cpp' object='libOPCODE_a-OPC_HybridModel.o' libtool=no @AMDEPBACKSLASH@
1049@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1050@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
1051
1052libOPCODE_a-OPC_HybridModel.obj: @TOPDIR@/OPCODE/OPC_HybridModel.cpp
1053@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`
1054@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po
1055@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_HybridModel.cpp' object='libOPCODE_a-OPC_HybridModel.obj' libtool=no @AMDEPBACKSLASH@
1056@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1057@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`
1058
1059libOPCODE_a-OPC_LSSCollider.o: @TOPDIR@/OPCODE/OPC_LSSCollider.cpp
1060@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
1061@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po
1062@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' object='libOPCODE_a-OPC_LSSCollider.o' libtool=no @AMDEPBACKSLASH@
1063@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1064@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
1065
1066libOPCODE_a-OPC_LSSCollider.obj: @TOPDIR@/OPCODE/OPC_LSSCollider.cpp
1067@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`
1068@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po
1069@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' object='libOPCODE_a-OPC_LSSCollider.obj' libtool=no @AMDEPBACKSLASH@
1070@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1071@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`
1072
1073libOPCODE_a-OPC_MeshInterface.o: @TOPDIR@/OPCODE/OPC_MeshInterface.cpp
1074@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
1075@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po
1076@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' object='libOPCODE_a-OPC_MeshInterface.o' libtool=no @AMDEPBACKSLASH@
1077@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1078@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
1079
1080libOPCODE_a-OPC_MeshInterface.obj: @TOPDIR@/OPCODE/OPC_MeshInterface.cpp
1081@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`
1082@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po
1083@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' object='libOPCODE_a-OPC_MeshInterface.obj' libtool=no @AMDEPBACKSLASH@
1084@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1085@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`
1086
1087libOPCODE_a-OPC_Model.o: @TOPDIR@/OPCODE/OPC_Model.cpp
1088@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
1089@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo $(DEPDIR)/libOPCODE_a-OPC_Model.Po
1090@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Model.cpp' object='libOPCODE_a-OPC_Model.o' libtool=no @AMDEPBACKSLASH@
1091@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1092@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
1093
1094libOPCODE_a-OPC_Model.obj: @TOPDIR@/OPCODE/OPC_Model.cpp
1095@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`
1096@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo $(DEPDIR)/libOPCODE_a-OPC_Model.Po
1097@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Model.cpp' object='libOPCODE_a-OPC_Model.obj' libtool=no @AMDEPBACKSLASH@
1098@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1099@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`
1100
1101libOPCODE_a-OPC_OBBCollider.o: @TOPDIR@/OPCODE/OPC_OBBCollider.cpp
1102@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
1103@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po
1104@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' object='libOPCODE_a-OPC_OBBCollider.o' libtool=no @AMDEPBACKSLASH@
1105@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1106@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
1107
1108libOPCODE_a-OPC_OBBCollider.obj: @TOPDIR@/OPCODE/OPC_OBBCollider.cpp
1109@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`
1110@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po
1111@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' object='libOPCODE_a-OPC_OBBCollider.obj' libtool=no @AMDEPBACKSLASH@
1112@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1113@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`
1114
1115libOPCODE_a-Opcode.o: @TOPDIR@/OPCODE/Opcode.cpp
1116@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
1117@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-Opcode.Tpo $(DEPDIR)/libOPCODE_a-Opcode.Po
1118@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Opcode.cpp' object='libOPCODE_a-Opcode.o' libtool=no @AMDEPBACKSLASH@
1119@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1120@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
1121
1122libOPCODE_a-Opcode.obj: @TOPDIR@/OPCODE/Opcode.cpp
1123@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`
1124@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-Opcode.Tpo $(DEPDIR)/libOPCODE_a-Opcode.Po
1125@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Opcode.cpp' object='libOPCODE_a-Opcode.obj' libtool=no @AMDEPBACKSLASH@
1126@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1127@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`
1128
1129libOPCODE_a-OPC_OptimizedTree.o: @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
1130@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
1131@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po
1132@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' object='libOPCODE_a-OPC_OptimizedTree.o' libtool=no @AMDEPBACKSLASH@
1133@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1134@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
1135
1136libOPCODE_a-OPC_OptimizedTree.obj: @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
1137@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`
1138@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po
1139@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' object='libOPCODE_a-OPC_OptimizedTree.obj' libtool=no @AMDEPBACKSLASH@
1140@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1141@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`
1142
1143libOPCODE_a-OPC_Picking.o: @TOPDIR@/OPCODE/OPC_Picking.cpp
1144@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
1145@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo $(DEPDIR)/libOPCODE_a-OPC_Picking.Po
1146@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Picking.cpp' object='libOPCODE_a-OPC_Picking.o' libtool=no @AMDEPBACKSLASH@
1147@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1148@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
1149
1150libOPCODE_a-OPC_Picking.obj: @TOPDIR@/OPCODE/OPC_Picking.cpp
1151@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`
1152@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo $(DEPDIR)/libOPCODE_a-OPC_Picking.Po
1153@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_Picking.cpp' object='libOPCODE_a-OPC_Picking.obj' libtool=no @AMDEPBACKSLASH@
1154@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1155@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`
1156
1157libOPCODE_a-OPC_PlanesCollider.o: @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
1158@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
1159@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po
1160@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' object='libOPCODE_a-OPC_PlanesCollider.o' libtool=no @AMDEPBACKSLASH@
1161@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1162@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
1163
1164libOPCODE_a-OPC_PlanesCollider.obj: @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
1165@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`
1166@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po
1167@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' object='libOPCODE_a-OPC_PlanesCollider.obj' libtool=no @AMDEPBACKSLASH@
1168@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1169@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`
1170
1171libOPCODE_a-OPC_RayCollider.o: @TOPDIR@/OPCODE/OPC_RayCollider.cpp
1172@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
1173@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po
1174@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_RayCollider.cpp' object='libOPCODE_a-OPC_RayCollider.o' libtool=no @AMDEPBACKSLASH@
1175@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1176@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
1177
1178libOPCODE_a-OPC_RayCollider.obj: @TOPDIR@/OPCODE/OPC_RayCollider.cpp
1179@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`
1180@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po
1181@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_RayCollider.cpp' object='libOPCODE_a-OPC_RayCollider.obj' libtool=no @AMDEPBACKSLASH@
1182@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1183@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`
1184
1185libOPCODE_a-OPC_SphereCollider.o: @TOPDIR@/OPCODE/OPC_SphereCollider.cpp
1186@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
1187@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po
1188@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' object='libOPCODE_a-OPC_SphereCollider.o' libtool=no @AMDEPBACKSLASH@
1189@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1190@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
1191
1192libOPCODE_a-OPC_SphereCollider.obj: @TOPDIR@/OPCODE/OPC_SphereCollider.cpp
1193@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`
1194@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po
1195@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' object='libOPCODE_a-OPC_SphereCollider.obj' libtool=no @AMDEPBACKSLASH@
1196@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1197@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`
1198
1199libOPCODE_a-OPC_SweepAndPrune.o: @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
1200@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
1201@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po
1202@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' object='libOPCODE_a-OPC_SweepAndPrune.o' libtool=no @AMDEPBACKSLASH@
1203@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1204@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
1205
1206libOPCODE_a-OPC_SweepAndPrune.obj: @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
1207@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`
1208@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po
1209@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' object='libOPCODE_a-OPC_SweepAndPrune.obj' libtool=no @AMDEPBACKSLASH@
1210@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1211@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`
1212
1213libOPCODE_a-OPC_TreeBuilders.o: @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
1214@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
1215@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po
1216@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' object='libOPCODE_a-OPC_TreeBuilders.o' libtool=no @AMDEPBACKSLASH@
1217@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1218@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
1219
1220libOPCODE_a-OPC_TreeBuilders.obj: @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
1221@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`
1222@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po
1223@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' object='libOPCODE_a-OPC_TreeBuilders.obj' libtool=no @AMDEPBACKSLASH@
1224@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1225@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`
1226
1227libOPCODE_a-OPC_TreeCollider.o: @TOPDIR@/OPCODE/OPC_TreeCollider.cpp
1228@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
1229@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po
1230@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' object='libOPCODE_a-OPC_TreeCollider.o' libtool=no @AMDEPBACKSLASH@
1231@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1232@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
1233
1234libOPCODE_a-OPC_TreeCollider.obj: @TOPDIR@/OPCODE/OPC_TreeCollider.cpp
1235@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`
1236@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po
1237@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' object='libOPCODE_a-OPC_TreeCollider.obj' libtool=no @AMDEPBACKSLASH@
1238@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1239@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`
1240
1241libOPCODE_a-OPC_VolumeCollider.o: @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
1242@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
1243@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po
1244@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' object='libOPCODE_a-OPC_VolumeCollider.o' libtool=no @AMDEPBACKSLASH@
1245@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1246@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
1247
1248libOPCODE_a-OPC_VolumeCollider.obj: @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
1249@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`
1250@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po
1251@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' object='libOPCODE_a-OPC_VolumeCollider.obj' libtool=no @AMDEPBACKSLASH@
1252@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1253@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`
1254
1255libOPCODE_a-IceAABB.o: @TOPDIR@/OPCODE/Ice/IceAABB.cpp
1256@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
1257@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceAABB.Tpo $(DEPDIR)/libOPCODE_a-IceAABB.Po
1258@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceAABB.cpp' object='libOPCODE_a-IceAABB.o' libtool=no @AMDEPBACKSLASH@
1259@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1260@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
1261
1262libOPCODE_a-IceAABB.obj: @TOPDIR@/OPCODE/Ice/IceAABB.cpp
1263@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`
1264@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceAABB.Tpo $(DEPDIR)/libOPCODE_a-IceAABB.Po
1265@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceAABB.cpp' object='libOPCODE_a-IceAABB.obj' libtool=no @AMDEPBACKSLASH@
1266@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1267@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`
1268
1269libOPCODE_a-IceContainer.o: @TOPDIR@/OPCODE/Ice/IceContainer.cpp
1270@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
1271@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceContainer.Tpo $(DEPDIR)/libOPCODE_a-IceContainer.Po
1272@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceContainer.cpp' object='libOPCODE_a-IceContainer.o' libtool=no @AMDEPBACKSLASH@
1273@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1274@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
1275
1276libOPCODE_a-IceContainer.obj: @TOPDIR@/OPCODE/Ice/IceContainer.cpp
1277@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`
1278@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceContainer.Tpo $(DEPDIR)/libOPCODE_a-IceContainer.Po
1279@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceContainer.cpp' object='libOPCODE_a-IceContainer.obj' libtool=no @AMDEPBACKSLASH@
1280@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1281@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`
1282
1283libOPCODE_a-IceHPoint.o: @TOPDIR@/OPCODE/Ice/IceHPoint.cpp
1284@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
1285@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo $(DEPDIR)/libOPCODE_a-IceHPoint.Po
1286@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' object='libOPCODE_a-IceHPoint.o' libtool=no @AMDEPBACKSLASH@
1287@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1288@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
1289
1290libOPCODE_a-IceHPoint.obj: @TOPDIR@/OPCODE/Ice/IceHPoint.cpp
1291@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`
1292@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo $(DEPDIR)/libOPCODE_a-IceHPoint.Po
1293@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' object='libOPCODE_a-IceHPoint.obj' libtool=no @AMDEPBACKSLASH@
1294@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1295@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`
1296
1297libOPCODE_a-IceIndexedTriangle.o: @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
1298@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
1299@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po
1300@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' object='libOPCODE_a-IceIndexedTriangle.o' libtool=no @AMDEPBACKSLASH@
1301@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1302@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
1303
1304libOPCODE_a-IceIndexedTriangle.obj: @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
1305@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`
1306@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po
1307@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' object='libOPCODE_a-IceIndexedTriangle.obj' libtool=no @AMDEPBACKSLASH@
1308@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1309@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`
1310
1311libOPCODE_a-IceMatrix3x3.o: @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
1312@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
1313@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po
1314@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' object='libOPCODE_a-IceMatrix3x3.o' libtool=no @AMDEPBACKSLASH@
1315@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1316@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
1317
1318libOPCODE_a-IceMatrix3x3.obj: @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
1319@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`
1320@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po
1321@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' object='libOPCODE_a-IceMatrix3x3.obj' libtool=no @AMDEPBACKSLASH@
1322@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1323@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`
1324
1325libOPCODE_a-IceMatrix4x4.o: @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
1326@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
1327@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po
1328@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' object='libOPCODE_a-IceMatrix4x4.o' libtool=no @AMDEPBACKSLASH@
1329@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1330@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
1331
1332libOPCODE_a-IceMatrix4x4.obj: @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
1333@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`
1334@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po
1335@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' object='libOPCODE_a-IceMatrix4x4.obj' libtool=no @AMDEPBACKSLASH@
1336@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1337@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`
1338
1339libOPCODE_a-IceOBB.o: @TOPDIR@/OPCODE/Ice/IceOBB.cpp
1340@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
1341@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceOBB.Tpo $(DEPDIR)/libOPCODE_a-IceOBB.Po
1342@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceOBB.cpp' object='libOPCODE_a-IceOBB.o' libtool=no @AMDEPBACKSLASH@
1343@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1344@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
1345
1346libOPCODE_a-IceOBB.obj: @TOPDIR@/OPCODE/Ice/IceOBB.cpp
1347@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`
1348@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceOBB.Tpo $(DEPDIR)/libOPCODE_a-IceOBB.Po
1349@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceOBB.cpp' object='libOPCODE_a-IceOBB.obj' libtool=no @AMDEPBACKSLASH@
1350@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1351@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`
1352
1353libOPCODE_a-IcePlane.o: @TOPDIR@/OPCODE/Ice/IcePlane.cpp
1354@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
1355@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IcePlane.Tpo $(DEPDIR)/libOPCODE_a-IcePlane.Po
1356@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IcePlane.cpp' object='libOPCODE_a-IcePlane.o' libtool=no @AMDEPBACKSLASH@
1357@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1358@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
1359
1360libOPCODE_a-IcePlane.obj: @TOPDIR@/OPCODE/Ice/IcePlane.cpp
1361@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`
1362@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IcePlane.Tpo $(DEPDIR)/libOPCODE_a-IcePlane.Po
1363@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IcePlane.cpp' object='libOPCODE_a-IcePlane.obj' libtool=no @AMDEPBACKSLASH@
1364@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1365@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`
1366
1367libOPCODE_a-IcePoint.o: @TOPDIR@/OPCODE/Ice/IcePoint.cpp
1368@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
1369@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IcePoint.Tpo $(DEPDIR)/libOPCODE_a-IcePoint.Po
1370@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IcePoint.cpp' object='libOPCODE_a-IcePoint.o' libtool=no @AMDEPBACKSLASH@
1371@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1372@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
1373
1374libOPCODE_a-IcePoint.obj: @TOPDIR@/OPCODE/Ice/IcePoint.cpp
1375@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`
1376@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IcePoint.Tpo $(DEPDIR)/libOPCODE_a-IcePoint.Po
1377@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IcePoint.cpp' object='libOPCODE_a-IcePoint.obj' libtool=no @AMDEPBACKSLASH@
1378@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1379@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`
1380
1381libOPCODE_a-IceRandom.o: @TOPDIR@/OPCODE/Ice/IceRandom.cpp
1382@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
1383@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRandom.Tpo $(DEPDIR)/libOPCODE_a-IceRandom.Po
1384@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRandom.cpp' object='libOPCODE_a-IceRandom.o' libtool=no @AMDEPBACKSLASH@
1385@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1386@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
1387
1388libOPCODE_a-IceRandom.obj: @TOPDIR@/OPCODE/Ice/IceRandom.cpp
1389@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`
1390@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRandom.Tpo $(DEPDIR)/libOPCODE_a-IceRandom.Po
1391@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRandom.cpp' object='libOPCODE_a-IceRandom.obj' libtool=no @AMDEPBACKSLASH@
1392@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1393@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`
1394
1395libOPCODE_a-IceRay.o: @TOPDIR@/OPCODE/Ice/IceRay.cpp
1396@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
1397@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRay.Tpo $(DEPDIR)/libOPCODE_a-IceRay.Po
1398@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRay.cpp' object='libOPCODE_a-IceRay.o' libtool=no @AMDEPBACKSLASH@
1399@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1400@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
1401
1402libOPCODE_a-IceRay.obj: @TOPDIR@/OPCODE/Ice/IceRay.cpp
1403@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`
1404@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRay.Tpo $(DEPDIR)/libOPCODE_a-IceRay.Po
1405@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRay.cpp' object='libOPCODE_a-IceRay.obj' libtool=no @AMDEPBACKSLASH@
1406@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1407@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`
1408
1409libOPCODE_a-IceRevisitedRadix.o: @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
1410@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
1411@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po
1412@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' object='libOPCODE_a-IceRevisitedRadix.o' libtool=no @AMDEPBACKSLASH@
1413@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1414@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
1415
1416libOPCODE_a-IceRevisitedRadix.obj: @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
1417@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`
1418@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po
1419@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' object='libOPCODE_a-IceRevisitedRadix.obj' libtool=no @AMDEPBACKSLASH@
1420@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1421@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`
1422
1423libOPCODE_a-IceSegment.o: @TOPDIR@/OPCODE/Ice/IceSegment.cpp
1424@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
1425@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceSegment.Tpo $(DEPDIR)/libOPCODE_a-IceSegment.Po
1426@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceSegment.cpp' object='libOPCODE_a-IceSegment.o' libtool=no @AMDEPBACKSLASH@
1427@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1428@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
1429
1430libOPCODE_a-IceSegment.obj: @TOPDIR@/OPCODE/Ice/IceSegment.cpp
1431@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`
1432@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceSegment.Tpo $(DEPDIR)/libOPCODE_a-IceSegment.Po
1433@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceSegment.cpp' object='libOPCODE_a-IceSegment.obj' libtool=no @AMDEPBACKSLASH@
1434@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1435@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`
1436
1437libOPCODE_a-IceTriangle.o: @TOPDIR@/OPCODE/Ice/IceTriangle.cpp
1438@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
1439@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceTriangle.Po
1440@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' object='libOPCODE_a-IceTriangle.o' libtool=no @AMDEPBACKSLASH@
1441@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1442@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
1443
1444libOPCODE_a-IceTriangle.obj: @TOPDIR@/OPCODE/Ice/IceTriangle.cpp
1445@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`
1446@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceTriangle.Po
1447@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' object='libOPCODE_a-IceTriangle.obj' libtool=no @AMDEPBACKSLASH@
1448@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1449@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`
1450
1451libOPCODE_a-IceUtils.o: @TOPDIR@/OPCODE/Ice/IceUtils.cpp
1452@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
1453@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceUtils.Tpo $(DEPDIR)/libOPCODE_a-IceUtils.Po
1454@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceUtils.cpp' object='libOPCODE_a-IceUtils.o' libtool=no @AMDEPBACKSLASH@
1455@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1456@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
1457
1458libOPCODE_a-IceUtils.obj: @TOPDIR@/OPCODE/Ice/IceUtils.cpp
1459@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`
1460@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libOPCODE_a-IceUtils.Tpo $(DEPDIR)/libOPCODE_a-IceUtils.Po
1461@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='@TOPDIR@/OPCODE/Ice/IceUtils.cpp' object='libOPCODE_a-IceUtils.obj' libtool=no @AMDEPBACKSLASH@
1462@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1463@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`
1464
1465libode_a-obstack.o: obstack.cpp
1466@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
1467@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-obstack.Tpo $(DEPDIR)/libode_a-obstack.Po
1468@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='obstack.cpp' object='libode_a-obstack.o' libtool=no @AMDEPBACKSLASH@
1469@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1470@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
1471
1472libode_a-obstack.obj: obstack.cpp
1473@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`
1474@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-obstack.Tpo $(DEPDIR)/libode_a-obstack.Po
1475@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='obstack.cpp' object='libode_a-obstack.obj' libtool=no @AMDEPBACKSLASH@
1476@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1477@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`
1478
1479libode_a-collision_util.o: collision_util.cpp
1480@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
1481@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_util.Tpo $(DEPDIR)/libode_a-collision_util.Po
1482@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_util.cpp' object='libode_a-collision_util.o' libtool=no @AMDEPBACKSLASH@
1483@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1484@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
1485
1486libode_a-collision_util.obj: collision_util.cpp
1487@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`
1488@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_util.Tpo $(DEPDIR)/libode_a-collision_util.Po
1489@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_util.cpp' object='libode_a-collision_util.obj' libtool=no @AMDEPBACKSLASH@
1490@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1491@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`
1492
1493libode_a-array.o: array.cpp
1494@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
1495@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-array.Tpo $(DEPDIR)/libode_a-array.Po
1496@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='array.cpp' object='libode_a-array.o' libtool=no @AMDEPBACKSLASH@
1497@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1498@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
1499
1500libode_a-array.obj: array.cpp
1501@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`
1502@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-array.Tpo $(DEPDIR)/libode_a-array.Po
1503@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='array.cpp' object='libode_a-array.obj' libtool=no @AMDEPBACKSLASH@
1504@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1505@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`
1506
1507libode_a-ode.o: ode.cpp
1508@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
1509@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-ode.Tpo $(DEPDIR)/libode_a-ode.Po
1510@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ode.cpp' object='libode_a-ode.o' libtool=no @AMDEPBACKSLASH@
1511@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1512@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
1513
1514libode_a-ode.obj: ode.cpp
1515@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`
1516@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-ode.Tpo $(DEPDIR)/libode_a-ode.Po
1517@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ode.cpp' object='libode_a-ode.obj' libtool=no @AMDEPBACKSLASH@
1518@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1519@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`
1520
1521libode_a-error.o: error.cpp
1522@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
1523@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-error.Tpo $(DEPDIR)/libode_a-error.Po
1524@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='error.cpp' object='libode_a-error.o' libtool=no @AMDEPBACKSLASH@
1525@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1526@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
1527
1528libode_a-error.obj: error.cpp
1529@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`
1530@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-error.Tpo $(DEPDIR)/libode_a-error.Po
1531@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='error.cpp' object='libode_a-error.obj' libtool=no @AMDEPBACKSLASH@
1532@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1533@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`
1534
1535libode_a-odemath.o: odemath.cpp
1536@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
1537@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-odemath.Tpo $(DEPDIR)/libode_a-odemath.Po
1538@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='odemath.cpp' object='libode_a-odemath.o' libtool=no @AMDEPBACKSLASH@
1539@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1540@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
1541
1542libode_a-odemath.obj: odemath.cpp
1543@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`
1544@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-odemath.Tpo $(DEPDIR)/libode_a-odemath.Po
1545@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='odemath.cpp' object='libode_a-odemath.obj' libtool=no @AMDEPBACKSLASH@
1546@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1547@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`
1548
1549libode_a-collision_kernel.o: collision_kernel.cpp
1550@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
1551@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_kernel.Tpo $(DEPDIR)/libode_a-collision_kernel.Po
1552@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_kernel.cpp' object='libode_a-collision_kernel.o' libtool=no @AMDEPBACKSLASH@
1553@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1554@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
1555
1556libode_a-collision_kernel.obj: collision_kernel.cpp
1557@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`
1558@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_kernel.Tpo $(DEPDIR)/libode_a-collision_kernel.Po
1559@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_kernel.cpp' object='libode_a-collision_kernel.obj' libtool=no @AMDEPBACKSLASH@
1560@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1561@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`
1562
1563libode_a-export-dif.o: export-dif.cpp
1564@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
1565@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-export-dif.Tpo $(DEPDIR)/libode_a-export-dif.Po
1566@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='export-dif.cpp' object='libode_a-export-dif.o' libtool=no @AMDEPBACKSLASH@
1567@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1568@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
1569
1570libode_a-export-dif.obj: export-dif.cpp
1571@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`
1572@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-export-dif.Tpo $(DEPDIR)/libode_a-export-dif.Po
1573@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='export-dif.cpp' object='libode_a-export-dif.obj' libtool=no @AMDEPBACKSLASH@
1574@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1575@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`
1576
1577libode_a-quickstep.o: quickstep.cpp
1578@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
1579@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-quickstep.Tpo $(DEPDIR)/libode_a-quickstep.Po
1580@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='quickstep.cpp' object='libode_a-quickstep.o' libtool=no @AMDEPBACKSLASH@
1581@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1582@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
1583
1584libode_a-quickstep.obj: quickstep.cpp
1585@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`
1586@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-quickstep.Tpo $(DEPDIR)/libode_a-quickstep.Po
1587@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='quickstep.cpp' object='libode_a-quickstep.obj' libtool=no @AMDEPBACKSLASH@
1588@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1589@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`
1590
1591libode_a-collision_quadtreespace.o: collision_quadtreespace.cpp
1592@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
1593@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_quadtreespace.Tpo $(DEPDIR)/libode_a-collision_quadtreespace.Po
1594@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_quadtreespace.cpp' object='libode_a-collision_quadtreespace.o' libtool=no @AMDEPBACKSLASH@
1595@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1596@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
1597
1598libode_a-collision_quadtreespace.obj: collision_quadtreespace.cpp
1599@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`
1600@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_quadtreespace.Tpo $(DEPDIR)/libode_a-collision_quadtreespace.Po
1601@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_quadtreespace.cpp' object='libode_a-collision_quadtreespace.obj' libtool=no @AMDEPBACKSLASH@
1602@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1603@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`
1604
1605libode_a-rotation.o: rotation.cpp
1606@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
1607@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-rotation.Tpo $(DEPDIR)/libode_a-rotation.Po
1608@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rotation.cpp' object='libode_a-rotation.o' libtool=no @AMDEPBACKSLASH@
1609@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1610@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
1611
1612libode_a-rotation.obj: rotation.cpp
1613@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`
1614@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-rotation.Tpo $(DEPDIR)/libode_a-rotation.Po
1615@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rotation.cpp' object='libode_a-rotation.obj' libtool=no @AMDEPBACKSLASH@
1616@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1617@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`
1618
1619libode_a-collision_space.o: collision_space.cpp
1620@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
1621@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_space.Tpo $(DEPDIR)/libode_a-collision_space.Po
1622@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_space.cpp' object='libode_a-collision_space.o' libtool=no @AMDEPBACKSLASH@
1623@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1624@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
1625
1626libode_a-collision_space.obj: collision_space.cpp
1627@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`
1628@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_space.Tpo $(DEPDIR)/libode_a-collision_space.Po
1629@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_space.cpp' object='libode_a-collision_space.obj' libtool=no @AMDEPBACKSLASH@
1630@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1631@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`
1632
1633libode_a-collision_cylinder_box.o: collision_cylinder_box.cpp
1634@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
1635@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_box.Tpo $(DEPDIR)/libode_a-collision_cylinder_box.Po
1636@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_box.cpp' object='libode_a-collision_cylinder_box.o' libtool=no @AMDEPBACKSLASH@
1637@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1638@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
1639
1640libode_a-collision_cylinder_box.obj: collision_cylinder_box.cpp
1641@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`
1642@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_box.Tpo $(DEPDIR)/libode_a-collision_cylinder_box.Po
1643@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_box.cpp' object='libode_a-collision_cylinder_box.obj' libtool=no @AMDEPBACKSLASH@
1644@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1645@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`
1646
1647libode_a-collision_cylinder_sphere.o: collision_cylinder_sphere.cpp
1648@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
1649@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo $(DEPDIR)/libode_a-collision_cylinder_sphere.Po
1650@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_sphere.cpp' object='libode_a-collision_cylinder_sphere.o' libtool=no @AMDEPBACKSLASH@
1651@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1652@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
1653
1654libode_a-collision_cylinder_sphere.obj: collision_cylinder_sphere.cpp
1655@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`
1656@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo $(DEPDIR)/libode_a-collision_cylinder_sphere.Po
1657@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_sphere.cpp' object='libode_a-collision_cylinder_sphere.obj' libtool=no @AMDEPBACKSLASH@
1658@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1659@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`
1660
1661libode_a-collision_cylinder_plane.o: collision_cylinder_plane.cpp
1662@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
1663@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo $(DEPDIR)/libode_a-collision_cylinder_plane.Po
1664@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_plane.cpp' object='libode_a-collision_cylinder_plane.o' libtool=no @AMDEPBACKSLASH@
1665@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1666@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
1667
1668libode_a-collision_cylinder_plane.obj: collision_cylinder_plane.cpp
1669@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`
1670@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo $(DEPDIR)/libode_a-collision_cylinder_plane.Po
1671@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_plane.cpp' object='libode_a-collision_cylinder_plane.obj' libtool=no @AMDEPBACKSLASH@
1672@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1673@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`
1674
1675libode_a-sphere.o: sphere.cpp
1676@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
1677@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-sphere.Tpo $(DEPDIR)/libode_a-sphere.Po
1678@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='sphere.cpp' object='libode_a-sphere.o' libtool=no @AMDEPBACKSLASH@
1679@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1680@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
1681
1682libode_a-sphere.obj: sphere.cpp
1683@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`
1684@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-sphere.Tpo $(DEPDIR)/libode_a-sphere.Po
1685@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='sphere.cpp' object='libode_a-sphere.obj' libtool=no @AMDEPBACKSLASH@
1686@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1687@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`
1688
1689libode_a-box.o: box.cpp
1690@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
1691@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-box.Tpo $(DEPDIR)/libode_a-box.Po
1692@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='box.cpp' object='libode_a-box.o' libtool=no @AMDEPBACKSLASH@
1693@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1694@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
1695
1696libode_a-box.obj: box.cpp
1697@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`
1698@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-box.Tpo $(DEPDIR)/libode_a-box.Po
1699@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='box.cpp' object='libode_a-box.obj' libtool=no @AMDEPBACKSLASH@
1700@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1701@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`
1702
1703libode_a-capsule.o: capsule.cpp
1704@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
1705@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-capsule.Tpo $(DEPDIR)/libode_a-capsule.Po
1706@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='capsule.cpp' object='libode_a-capsule.o' libtool=no @AMDEPBACKSLASH@
1707@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1708@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
1709
1710libode_a-capsule.obj: capsule.cpp
1711@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`
1712@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-capsule.Tpo $(DEPDIR)/libode_a-capsule.Po
1713@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='capsule.cpp' object='libode_a-capsule.obj' libtool=no @AMDEPBACKSLASH@
1714@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1715@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`
1716
1717libode_a-plane.o: plane.cpp
1718@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
1719@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-plane.Tpo $(DEPDIR)/libode_a-plane.Po
1720@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='plane.cpp' object='libode_a-plane.o' libtool=no @AMDEPBACKSLASH@
1721@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1722@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
1723
1724libode_a-plane.obj: plane.cpp
1725@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`
1726@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-plane.Tpo $(DEPDIR)/libode_a-plane.Po
1727@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='plane.cpp' object='libode_a-plane.obj' libtool=no @AMDEPBACKSLASH@
1728@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1729@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`
1730
1731libode_a-ray.o: ray.cpp
1732@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
1733@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-ray.Tpo $(DEPDIR)/libode_a-ray.Po
1734@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ray.cpp' object='libode_a-ray.o' libtool=no @AMDEPBACKSLASH@
1735@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1736@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
1737
1738libode_a-ray.obj: ray.cpp
1739@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`
1740@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-ray.Tpo $(DEPDIR)/libode_a-ray.Po
1741@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ray.cpp' object='libode_a-ray.obj' libtool=no @AMDEPBACKSLASH@
1742@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1743@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`
1744
1745libode_a-cylinder.o: cylinder.cpp
1746@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
1747@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-cylinder.Tpo $(DEPDIR)/libode_a-cylinder.Po
1748@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='cylinder.cpp' object='libode_a-cylinder.o' libtool=no @AMDEPBACKSLASH@
1749@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1750@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
1751
1752libode_a-cylinder.obj: cylinder.cpp
1753@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`
1754@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-cylinder.Tpo $(DEPDIR)/libode_a-cylinder.Po
1755@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='cylinder.cpp' object='libode_a-cylinder.obj' libtool=no @AMDEPBACKSLASH@
1756@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1757@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`
1758
1759libode_a-convex.o: convex.cpp
1760@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
1761@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-convex.Tpo $(DEPDIR)/libode_a-convex.Po
1762@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='convex.cpp' object='libode_a-convex.o' libtool=no @AMDEPBACKSLASH@
1763@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1764@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
1765
1766libode_a-convex.obj: convex.cpp
1767@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`
1768@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-convex.Tpo $(DEPDIR)/libode_a-convex.Po
1769@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='convex.cpp' object='libode_a-convex.obj' libtool=no @AMDEPBACKSLASH@
1770@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1771@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`
1772
1773libode_a-joint.o: joint.cpp
1774@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
1775@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-joint.Tpo $(DEPDIR)/libode_a-joint.Po
1776@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='joint.cpp' object='libode_a-joint.o' libtool=no @AMDEPBACKSLASH@
1777@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1778@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
1779
1780libode_a-joint.obj: joint.cpp
1781@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`
1782@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-joint.Tpo $(DEPDIR)/libode_a-joint.Po
1783@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='joint.cpp' object='libode_a-joint.obj' libtool=no @AMDEPBACKSLASH@
1784@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1785@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`
1786
1787libode_a-step.o: step.cpp
1788@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
1789@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-step.Tpo $(DEPDIR)/libode_a-step.Po
1790@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='step.cpp' object='libode_a-step.o' libtool=no @AMDEPBACKSLASH@
1791@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1792@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
1793
1794libode_a-step.obj: step.cpp
1795@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`
1796@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-step.Tpo $(DEPDIR)/libode_a-step.Po
1797@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='step.cpp' object='libode_a-step.obj' libtool=no @AMDEPBACKSLASH@
1798@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1799@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`
1800
1801libode_a-collision_transform.o: collision_transform.cpp
1802@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
1803@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_transform.Tpo $(DEPDIR)/libode_a-collision_transform.Po
1804@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_transform.cpp' object='libode_a-collision_transform.o' libtool=no @AMDEPBACKSLASH@
1805@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1806@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
1807
1808libode_a-collision_transform.obj: collision_transform.cpp
1809@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`
1810@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_transform.Tpo $(DEPDIR)/libode_a-collision_transform.Po
1811@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_transform.cpp' object='libode_a-collision_transform.obj' libtool=no @AMDEPBACKSLASH@
1812@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1813@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`
1814
1815libode_a-lcp.o: lcp.cpp
1816@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
1817@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-lcp.Tpo $(DEPDIR)/libode_a-lcp.Po
1818@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lcp.cpp' object='libode_a-lcp.o' libtool=no @AMDEPBACKSLASH@
1819@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1820@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
1821
1822libode_a-lcp.obj: lcp.cpp
1823@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`
1824@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-lcp.Tpo $(DEPDIR)/libode_a-lcp.Po
1825@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lcp.cpp' object='libode_a-lcp.obj' libtool=no @AMDEPBACKSLASH@
1826@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1827@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`
1828
1829libode_a-stepfast.o: stepfast.cpp
1830@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
1831@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-stepfast.Tpo $(DEPDIR)/libode_a-stepfast.Po
1832@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='stepfast.cpp' object='libode_a-stepfast.o' libtool=no @AMDEPBACKSLASH@
1833@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1834@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
1835
1836libode_a-stepfast.obj: stepfast.cpp
1837@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`
1838@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-stepfast.Tpo $(DEPDIR)/libode_a-stepfast.Po
1839@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='stepfast.cpp' object='libode_a-stepfast.obj' libtool=no @AMDEPBACKSLASH@
1840@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1841@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`
1842
1843libode_a-mass.o: mass.cpp
1844@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
1845@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-mass.Tpo $(DEPDIR)/libode_a-mass.Po
1846@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mass.cpp' object='libode_a-mass.o' libtool=no @AMDEPBACKSLASH@
1847@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1848@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
1849
1850libode_a-mass.obj: mass.cpp
1851@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`
1852@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-mass.Tpo $(DEPDIR)/libode_a-mass.Po
1853@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mass.cpp' object='libode_a-mass.obj' libtool=no @AMDEPBACKSLASH@
1854@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1855@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`
1856
1857libode_a-testing.o: testing.cpp
1858@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
1859@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-testing.Tpo $(DEPDIR)/libode_a-testing.Po
1860@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='testing.cpp' object='libode_a-testing.o' libtool=no @AMDEPBACKSLASH@
1861@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1862@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
1863
1864libode_a-testing.obj: testing.cpp
1865@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`
1866@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-testing.Tpo $(DEPDIR)/libode_a-testing.Po
1867@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='testing.cpp' object='libode_a-testing.obj' libtool=no @AMDEPBACKSLASH@
1868@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1869@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`
1870
1871libode_a-mat.o: mat.cpp
1872@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
1873@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-mat.Tpo $(DEPDIR)/libode_a-mat.Po
1874@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mat.cpp' object='libode_a-mat.o' libtool=no @AMDEPBACKSLASH@
1875@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1876@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
1877
1878libode_a-mat.obj: mat.cpp
1879@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`
1880@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-mat.Tpo $(DEPDIR)/libode_a-mat.Po
1881@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mat.cpp' object='libode_a-mat.obj' libtool=no @AMDEPBACKSLASH@
1882@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1883@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`
1884
1885libode_a-timer.o: timer.cpp
1886@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
1887@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-timer.Tpo $(DEPDIR)/libode_a-timer.Po
1888@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='timer.cpp' object='libode_a-timer.o' libtool=no @AMDEPBACKSLASH@
1889@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1890@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
1891
1892libode_a-timer.obj: timer.cpp
1893@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`
1894@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-timer.Tpo $(DEPDIR)/libode_a-timer.Po
1895@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='timer.cpp' object='libode_a-timer.obj' libtool=no @AMDEPBACKSLASH@
1896@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1897@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`
1898
1899libode_a-matrix.o: matrix.cpp
1900@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
1901@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-matrix.Tpo $(DEPDIR)/libode_a-matrix.Po
1902@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='matrix.cpp' object='libode_a-matrix.o' libtool=no @AMDEPBACKSLASH@
1903@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1904@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
1905
1906libode_a-matrix.obj: matrix.cpp
1907@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`
1908@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-matrix.Tpo $(DEPDIR)/libode_a-matrix.Po
1909@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='matrix.cpp' object='libode_a-matrix.obj' libtool=no @AMDEPBACKSLASH@
1910@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1911@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`
1912
1913libode_a-util.o: util.cpp
1914@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
1915@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-util.Tpo $(DEPDIR)/libode_a-util.Po
1916@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='util.cpp' object='libode_a-util.o' libtool=no @AMDEPBACKSLASH@
1917@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1918@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
1919
1920libode_a-util.obj: util.cpp
1921@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`
1922@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-util.Tpo $(DEPDIR)/libode_a-util.Po
1923@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='util.cpp' object='libode_a-util.obj' libtool=no @AMDEPBACKSLASH@
1924@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1925@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`
1926
1927libode_a-memory.o: memory.cpp
1928@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
1929@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-memory.Tpo $(DEPDIR)/libode_a-memory.Po
1930@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='memory.cpp' object='libode_a-memory.o' libtool=no @AMDEPBACKSLASH@
1931@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1932@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
1933
1934libode_a-memory.obj: memory.cpp
1935@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`
1936@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-memory.Tpo $(DEPDIR)/libode_a-memory.Po
1937@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='memory.cpp' object='libode_a-memory.obj' libtool=no @AMDEPBACKSLASH@
1938@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1939@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`
1940
1941libode_a-misc.o: misc.cpp
1942@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
1943@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-misc.Tpo $(DEPDIR)/libode_a-misc.Po
1944@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='misc.cpp' object='libode_a-misc.o' libtool=no @AMDEPBACKSLASH@
1945@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1946@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
1947
1948libode_a-misc.obj: misc.cpp
1949@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`
1950@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-misc.Tpo $(DEPDIR)/libode_a-misc.Po
1951@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='misc.cpp' object='libode_a-misc.obj' libtool=no @AMDEPBACKSLASH@
1952@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1953@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`
1954
1955libode_a-heightfield.o: heightfield.cpp
1956@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
1957@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-heightfield.Tpo $(DEPDIR)/libode_a-heightfield.Po
1958@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='heightfield.cpp' object='libode_a-heightfield.o' libtool=no @AMDEPBACKSLASH@
1959@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1960@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
1961
1962libode_a-heightfield.obj: heightfield.cpp
1963@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`
1964@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-heightfield.Tpo $(DEPDIR)/libode_a-heightfield.Po
1965@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='heightfield.cpp' object='libode_a-heightfield.obj' libtool=no @AMDEPBACKSLASH@
1966@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1967@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`
1968
1969libode_a-collision_trimesh_gimpact.o: collision_trimesh_gimpact.cpp
1970@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
1971@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo $(DEPDIR)/libode_a-collision_trimesh_gimpact.Po
1972@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_gimpact.cpp' object='libode_a-collision_trimesh_gimpact.o' libtool=no @AMDEPBACKSLASH@
1973@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1974@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
1975
1976libode_a-collision_trimesh_gimpact.obj: collision_trimesh_gimpact.cpp
1977@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`
1978@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo $(DEPDIR)/libode_a-collision_trimesh_gimpact.Po
1979@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_gimpact.cpp' object='libode_a-collision_trimesh_gimpact.obj' libtool=no @AMDEPBACKSLASH@
1980@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1981@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`
1982
1983libode_a-collision_trimesh_trimesh.o: collision_trimesh_trimesh.cpp
1984@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
1985@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo $(DEPDIR)/libode_a-collision_trimesh_trimesh.Po
1986@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_trimesh.cpp' object='libode_a-collision_trimesh_trimesh.o' libtool=no @AMDEPBACKSLASH@
1987@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1988@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
1989
1990libode_a-collision_trimesh_trimesh.obj: collision_trimesh_trimesh.cpp
1991@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`
1992@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo $(DEPDIR)/libode_a-collision_trimesh_trimesh.Po
1993@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_trimesh.cpp' object='libode_a-collision_trimesh_trimesh.obj' libtool=no @AMDEPBACKSLASH@
1994@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1995@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`
1996
1997libode_a-collision_trimesh_sphere.o: collision_trimesh_sphere.cpp
1998@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
1999@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo $(DEPDIR)/libode_a-collision_trimesh_sphere.Po
2000@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_sphere.cpp' object='libode_a-collision_trimesh_sphere.o' libtool=no @AMDEPBACKSLASH@
2001@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2002@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
2003
2004libode_a-collision_trimesh_sphere.obj: collision_trimesh_sphere.cpp
2005@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`
2006@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo $(DEPDIR)/libode_a-collision_trimesh_sphere.Po
2007@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_sphere.cpp' object='libode_a-collision_trimesh_sphere.obj' libtool=no @AMDEPBACKSLASH@
2008@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2009@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`
2010
2011libode_a-collision_trimesh_ray.o: collision_trimesh_ray.cpp
2012@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
2013@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo $(DEPDIR)/libode_a-collision_trimesh_ray.Po
2014@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_ray.cpp' object='libode_a-collision_trimesh_ray.o' libtool=no @AMDEPBACKSLASH@
2015@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2016@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
2017
2018libode_a-collision_trimesh_ray.obj: collision_trimesh_ray.cpp
2019@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`
2020@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo $(DEPDIR)/libode_a-collision_trimesh_ray.Po
2021@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_ray.cpp' object='libode_a-collision_trimesh_ray.obj' libtool=no @AMDEPBACKSLASH@
2022@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2023@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`
2024
2025libode_a-collision_trimesh_opcode.o: collision_trimesh_opcode.cpp
2026@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
2027@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo $(DEPDIR)/libode_a-collision_trimesh_opcode.Po
2028@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_opcode.cpp' object='libode_a-collision_trimesh_opcode.o' libtool=no @AMDEPBACKSLASH@
2029@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2030@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
2031
2032libode_a-collision_trimesh_opcode.obj: collision_trimesh_opcode.cpp
2033@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`
2034@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo $(DEPDIR)/libode_a-collision_trimesh_opcode.Po
2035@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_opcode.cpp' object='libode_a-collision_trimesh_opcode.obj' libtool=no @AMDEPBACKSLASH@
2036@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2037@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`
2038
2039libode_a-collision_trimesh_box.o: collision_trimesh_box.cpp
2040@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
2041@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_box.Tpo $(DEPDIR)/libode_a-collision_trimesh_box.Po
2042@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_box.cpp' object='libode_a-collision_trimesh_box.o' libtool=no @AMDEPBACKSLASH@
2043@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2044@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
2045
2046libode_a-collision_trimesh_box.obj: collision_trimesh_box.cpp
2047@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`
2048@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_box.Tpo $(DEPDIR)/libode_a-collision_trimesh_box.Po
2049@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_box.cpp' object='libode_a-collision_trimesh_box.obj' libtool=no @AMDEPBACKSLASH@
2050@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2051@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`
2052
2053libode_a-collision_trimesh_ccylinder.o: collision_trimesh_ccylinder.cpp
2054@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
2055@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po
2056@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_ccylinder.cpp' object='libode_a-collision_trimesh_ccylinder.o' libtool=no @AMDEPBACKSLASH@
2057@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2058@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
2059
2060libode_a-collision_trimesh_ccylinder.obj: collision_trimesh_ccylinder.cpp
2061@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`
2062@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po
2063@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_ccylinder.cpp' object='libode_a-collision_trimesh_ccylinder.obj' libtool=no @AMDEPBACKSLASH@
2064@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2065@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`
2066
2067libode_a-collision_trimesh_distance.o: collision_trimesh_distance.cpp
2068@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
2069@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo $(DEPDIR)/libode_a-collision_trimesh_distance.Po
2070@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_distance.cpp' object='libode_a-collision_trimesh_distance.o' libtool=no @AMDEPBACKSLASH@
2071@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2072@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
2073
2074libode_a-collision_trimesh_distance.obj: collision_trimesh_distance.cpp
2075@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`
2076@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo $(DEPDIR)/libode_a-collision_trimesh_distance.Po
2077@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_distance.cpp' object='libode_a-collision_trimesh_distance.obj' libtool=no @AMDEPBACKSLASH@
2078@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2079@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`
2080
2081libode_a-collision_cylinder_trimesh.o: collision_cylinder_trimesh.cpp
2082@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
2083@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo $(DEPDIR)/libode_a-collision_cylinder_trimesh.Po
2084@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_trimesh.cpp' object='libode_a-collision_cylinder_trimesh.o' libtool=no @AMDEPBACKSLASH@
2085@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2086@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
2087
2088libode_a-collision_cylinder_trimesh.obj: collision_cylinder_trimesh.cpp
2089@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`
2090@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo $(DEPDIR)/libode_a-collision_cylinder_trimesh.Po
2091@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_cylinder_trimesh.cpp' object='libode_a-collision_cylinder_trimesh.obj' libtool=no @AMDEPBACKSLASH@
2092@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2093@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`
2094
2095libode_a-collision_trimesh_plane.o: collision_trimesh_plane.cpp
2096@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
2097@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo $(DEPDIR)/libode_a-collision_trimesh_plane.Po
2098@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_plane.cpp' object='libode_a-collision_trimesh_plane.o' libtool=no @AMDEPBACKSLASH@
2099@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2100@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
2101
2102libode_a-collision_trimesh_plane.obj: collision_trimesh_plane.cpp
2103@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`
2104@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo $(DEPDIR)/libode_a-collision_trimesh_plane.Po
2105@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='collision_trimesh_plane.cpp' object='libode_a-collision_trimesh_plane.obj' libtool=no @AMDEPBACKSLASH@
2106@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2107@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`
2108
2109ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
2110 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
2111 unique=`for i in $$list; do \
2112 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
2113 done | \
2114 $(AWK) ' { files[$$0] = 1; } \
2115 END { for (i in files) print i; }'`; \
2116 mkid -fID $$unique
2117tags: TAGS
2118
2119TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
2120 $(TAGS_FILES) $(LISP)
2121 tags=; \
2122 here=`pwd`; \
2123 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
2124 unique=`for i in $$list; do \
2125 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
2126 done | \
2127 $(AWK) ' { files[$$0] = 1; } \
2128 END { for (i in files) print i; }'`; \
2129 if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
2130 test -n "$$unique" || unique=$$empty_fix; \
2131 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
2132 $$tags $$unique; \
2133 fi
2134ctags: CTAGS
2135CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
2136 $(TAGS_FILES) $(LISP)
2137 tags=; \
2138 here=`pwd`; \
2139 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
2140 unique=`for i in $$list; do \
2141 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
2142 done | \
2143 $(AWK) ' { files[$$0] = 1; } \
2144 END { for (i in files) print i; }'`; \
2145 test -z "$(CTAGS_ARGS)$$tags$$unique" \
2146 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
2147 $$tags $$unique
2148
2149GTAGS:
2150 here=`$(am__cd) $(top_builddir) && pwd` \
2151 && cd $(top_srcdir) \
2152 && gtags -i $(GTAGS_ARGS) $$here
2153
2154distclean-tags:
2155 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
2156
2157distdir: $(DISTFILES)
2158 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
2159 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
2160 list='$(DISTFILES)'; \
2161 dist_files=`for file in $$list; do echo $$file; done | \
2162 sed -e "s|^$$srcdirstrip/||;t" \
2163 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
2164 case $$dist_files in \
2165 */*) $(MKDIR_P) `echo "$$dist_files" | \
2166 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
2167 sort -u` ;; \
2168 esac; \
2169 for file in $$dist_files; do \
2170 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
2171 if test -d $$d/$$file; then \
2172 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
2173 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
2174 cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
2175 fi; \
2176 cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
2177 else \
2178 test -f $(distdir)/$$file \
2179 || cp -p $$d/$$file $(distdir)/$$file \
2180 || exit 1; \
2181 fi; \
2182 done
2183check-am: all-am
2184check: check-am
2185all-am: Makefile $(LIBRARIES) $(PROGRAMS)
2186installdirs:
2187 for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(traplibdir)"; do \
2188 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
2189 done
2190install: install-am
2191install-exec: install-exec-am
2192install-data: install-data-am
2193uninstall: uninstall-am
2194
2195install-am: all-am
2196 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
2197
2198installcheck: installcheck-am
2199install-strip:
2200 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
2201 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
2202 `test -z '$(STRIP)' || \
2203 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
2204mostlyclean-generic:
2205
2206clean-generic:
2207
2208distclean-generic:
2209 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
2210
2211maintainer-clean-generic:
2212 @echo "This command is intended for maintainers to use"
2213 @echo "it deletes files that may require special tools to rebuild."
2214clean: clean-am
2215
2216clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \
2217 clean-traplibPROGRAMS mostlyclean-am
2218
2219distclean: distclean-am
2220 -rm -rf ./$(DEPDIR)
2221 -rm -f Makefile
2222distclean-am: clean-am distclean-compile distclean-generic \
2223 distclean-tags
2224
2225dvi: dvi-am
2226
2227dvi-am:
2228
2229html: html-am
2230
2231info: info-am
2232
2233info-am:
2234
2235install-data-am: install-traplibPROGRAMS
2236
2237install-dvi: install-dvi-am
2238
2239install-exec-am: install-libLIBRARIES
2240
2241install-html: install-html-am
2242
2243install-info: install-info-am
2244
2245install-man:
2246
2247install-pdf: install-pdf-am
2248
2249install-ps: install-ps-am
2250
2251installcheck-am:
2252
2253maintainer-clean: maintainer-clean-am
2254 -rm -rf ./$(DEPDIR)
2255 -rm -f Makefile
2256maintainer-clean-am: distclean-am maintainer-clean-generic
2257
2258mostlyclean: mostlyclean-am
2259
2260mostlyclean-am: mostlyclean-compile mostlyclean-generic
2261
2262pdf: pdf-am
2263
2264pdf-am:
2265
2266ps: ps-am
2267
2268ps-am:
2269
2270uninstall-am: uninstall-libLIBRARIES uninstall-traplibPROGRAMS
2271
2272.MAKE: install-am install-strip
2273
2274.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
2275 clean-libLIBRARIES clean-noinstLIBRARIES clean-traplibPROGRAMS \
2276 ctags distclean distclean-compile distclean-generic \
2277 distclean-tags distdir dvi dvi-am html html-am info info-am \
2278 install install-am install-data install-data-am install-dvi \
2279 install-dvi-am install-exec install-exec-am install-html \
2280 install-html-am install-info install-info-am \
2281 install-libLIBRARIES install-man install-pdf install-pdf-am \
2282 install-ps install-ps-am install-strip install-traplibPROGRAMS \
2283 installcheck installcheck-am installdirs maintainer-clean \
2284 maintainer-clean-generic mostlyclean mostlyclean-compile \
2285 mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
2286 uninstall-am uninstall-libLIBRARIES uninstall-traplibPROGRAMS
2287
2288# Tell versions [3.59,3.63) of GNU make to not export all variables.
2289# Otherwise a system limit (for SysV at least) may be exceeded.
2290.NOEXPORT:
diff --git a/libraries/ode-0.9/ode/src/array.cpp b/libraries/ode-0.9/ode/src/array.cpp
deleted file mode 100644
index cbb1a6e..0000000
--- a/libraries/ode-0.9/ode/src/array.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/memory.h>
25#include <ode/error.h>
26#include "array.h"
27
28
29static inline int roundUpToPowerOfTwo (int x)
30{
31 int i = 1;
32 while (i < x) i <<= 1;
33 return i;
34}
35
36
37void dArrayBase::_freeAll (int sizeofT)
38{
39 if (_data) {
40 if (_data == this+1) return; // if constructLocalArray() was called
41 dFree (_data,_anum * sizeofT);
42 }
43}
44
45
46void dArrayBase::_setSize (int newsize, int sizeofT)
47{
48 if (newsize < 0) return;
49 if (newsize > _anum) {
50 if (_data == this+1) {
51 // this is a no-no, because constructLocalArray() was called
52 dDebug (0,"setSize() out of space in LOCAL array");
53 }
54 int newanum = roundUpToPowerOfTwo (newsize);
55 if (_data) _data = dRealloc (_data, _anum*sizeofT, newanum*sizeofT);
56 else _data = dAlloc (newanum*sizeofT);
57 _anum = newanum;
58 }
59 _size = newsize;
60}
61
62
63void * dArrayBase::operator new (size_t size)
64{
65 return dAlloc (size);
66}
67
68
69void dArrayBase::operator delete (void *ptr, size_t size)
70{
71 dFree (ptr,size);
72}
73
74
75void dArrayBase::constructLocalArray (int __anum)
76{
77 _size = 0;
78 _anum = __anum;
79 _data = this+1;
80}
diff --git a/libraries/ode-0.9/ode/src/array.h b/libraries/ode-0.9/ode/src/array.h
deleted file mode 100644
index 307206c..0000000
--- a/libraries/ode-0.9/ode/src/array.h
+++ /dev/null
@@ -1,135 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/* this comes from the `reuse' library. copy any changes back to the source.
24 *
25 * Variable sized array template. The array is always stored in a contiguous
26 * chunk. The array can be resized. A size increase will cause more memory
27 * to be allocated, and may result in relocation of the array memory.
28 * A size decrease has no effect on the memory allocation.
29 *
30 * Array elements with constructors or destructors are not supported!
31 * But if you must have such elements, here's what to know/do:
32 * - Bitwise copy is used when copying whole arrays.
33 * - When copying individual items (via push(), insert() etc) the `='
34 * (equals) operator is used. Thus you should define this operator to do
35 * a bitwise copy. You should probably also define the copy constructor.
36 */
37
38
39#ifndef _ODE_ARRAY_H_
40#define _ODE_ARRAY_H_
41
42#include <ode/config.h>
43
44
45// this base class has no constructors or destructor, for your convenience.
46
47class dArrayBase {
48protected:
49 int _size; // number of elements in `data'
50 int _anum; // allocated number of elements in `data'
51 void *_data; // array data
52
53 void _freeAll (int sizeofT);
54 void _setSize (int newsize, int sizeofT);
55 // set the array size to `newsize', allocating more memory if necessary.
56 // if newsize>_anum and is a power of two then this is guaranteed to
57 // set _size and _anum to newsize.
58
59public:
60 // not: dArrayBase () { _size=0; _anum=0; _data=0; }
61
62 int size() const { return _size; }
63 int allocatedSize() const { return _anum; }
64 void * operator new (size_t size);
65 void operator delete (void *ptr, size_t size);
66
67 void constructor() { _size=0; _anum=0; _data=0; }
68 // if this structure is allocated with malloc() instead of new, you can
69 // call this to set it up.
70
71 void constructLocalArray (int __anum);
72 // this helper function allows non-reallocating arrays to be constructed
73 // on the stack (or in the heap if necessary). this is something of a
74 // kludge and should be used with extreme care. this function acts like
75 // a constructor - it is called on uninitialized memory that will hold the
76 // Array structure and the data. __anum is the number of elements that
77 // are allocated. the memory MUST be allocated with size:
78 // sizeof(ArrayBase) + __anum*sizeof(T)
79 // arrays allocated this way will never try to reallocate or free the
80 // memory - that's your job.
81};
82
83
84template <class T> class dArray : public dArrayBase {
85public:
86 void equals (const dArray<T> &x) {
87 setSize (x.size());
88 memcpy (_data,x._data,x._size * sizeof(T));
89 }
90
91 dArray () { constructor(); }
92 dArray (const dArray<T> &x) { constructor(); equals (x); }
93 ~dArray () { _freeAll(sizeof(T)); }
94 void setSize (int newsize) { _setSize (newsize,sizeof(T)); }
95 T *data() const { return (T*) _data; }
96 T & operator[] (int i) const { return ((T*)_data)[i]; }
97 void operator = (const dArray<T> &x) { equals (x); }
98
99 void push (const T item) {
100 if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
101 memcpy (&(((T*)_data)[_size-1]), &item, sizeof(T));
102 }
103
104 void swap (dArray<T> &x) {
105 int tmp1;
106 void *tmp2;
107 tmp1=_size; _size=x._size; x._size=tmp1;
108 tmp1=_anum; _anum=x._anum; x._anum=tmp1;
109 tmp2=_data; _data=x._data; x._data=tmp2;
110 }
111
112 // insert the item at the position `i'. if i<0 then add the item to the
113 // start, if i >= size then add the item to the end of the array.
114 void insert (int i, const T item) {
115 if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
116 if (i >= (_size-1)) i = _size-1; // add to end
117 else {
118 if (i < 0) i=0; // add to start
119 int n = _size-1-i;
120 if (n>0) memmove (((T*)_data) + i+1, ((T*)_data) + i, n*sizeof(T));
121 }
122 ((T*)_data)[i] = item;
123 }
124
125 void remove (int i) {
126 if (i >= 0 && i < _size) { // passing this test guarantees size>0
127 int n = _size-1-i;
128 if (n>0) memmove (((T*)_data) + i, ((T*)_data) + i+1, n*sizeof(T));
129 _size--;
130 }
131 }
132};
133
134
135#endif
diff --git a/libraries/ode-0.9/ode/src/box.cpp b/libraries/ode-0.9/ode/src/box.cpp
deleted file mode 100644
index f328651..0000000
--- a/libraries/ode-0.9/ode/src/box.cpp
+++ /dev/null
@@ -1,847 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45//****************************************************************************
46// box public API
47
48dxBox::dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz) : dxGeom (space,1)
49{
50 dAASSERT (lx >= 0 && ly >= 0 && lz >= 0);
51 type = dBoxClass;
52 side[0] = lx;
53 side[1] = ly;
54 side[2] = lz;
55}
56
57
58void dxBox::computeAABB()
59{
60 const dMatrix3& R = final_posr->R;
61 const dVector3& pos = final_posr->pos;
62
63 dReal xrange = REAL(0.5) * (dFabs (R[0] * side[0]) +
64 dFabs (R[1] * side[1]) + dFabs (R[2] * side[2]));
65 dReal yrange = REAL(0.5) * (dFabs (R[4] * side[0]) +
66 dFabs (R[5] * side[1]) + dFabs (R[6] * side[2]));
67 dReal zrange = REAL(0.5) * (dFabs (R[8] * side[0]) +
68 dFabs (R[9] * side[1]) + dFabs (R[10] * side[2]));
69 aabb[0] = pos[0] - xrange;
70 aabb[1] = pos[0] + xrange;
71 aabb[2] = pos[1] - yrange;
72 aabb[3] = pos[1] + yrange;
73 aabb[4] = pos[2] - zrange;
74 aabb[5] = pos[2] + zrange;
75}
76
77
78dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz)
79{
80 return new dxBox (space,lx,ly,lz);
81}
82
83
84void dGeomBoxSetLengths (dGeomID g, dReal lx, dReal ly, dReal lz)
85{
86 dUASSERT (g && g->type == dBoxClass,"argument not a box");
87 dAASSERT (lx > 0 && ly > 0 && lz > 0);
88 dxBox *b = (dxBox*) g;
89 b->side[0] = lx;
90 b->side[1] = ly;
91 b->side[2] = lz;
92 dGeomMoved (g);
93}
94
95
96void dGeomBoxGetLengths (dGeomID g, dVector3 result)
97{
98 dUASSERT (g && g->type == dBoxClass,"argument not a box");
99 dxBox *b = (dxBox*) g;
100 result[0] = b->side[0];
101 result[1] = b->side[1];
102 result[2] = b->side[2];
103}
104
105
106dReal dGeomBoxPointDepth (dGeomID g, dReal x, dReal y, dReal z)
107{
108 dUASSERT (g && g->type == dBoxClass,"argument not a box");
109 g->recomputePosr();
110 dxBox *b = (dxBox*) g;
111
112 // Set p = (x,y,z) relative to box center
113 //
114 // This will be (0,0,0) if the point is at (side[0]/2,side[1]/2,side[2]/2)
115
116 dVector3 p,q;
117
118 p[0] = x - b->final_posr->pos[0];
119 p[1] = y - b->final_posr->pos[1];
120 p[2] = z - b->final_posr->pos[2];
121
122 // Rotate p into box's coordinate frame, so we can
123 // treat the OBB as an AABB
124
125 dMULTIPLY1_331 (q,b->final_posr->R,p);
126
127 // Record distance from point to each successive box side, and see
128 // if the point is inside all six sides
129
130 dReal dist[6];
131 int i;
132
133 bool inside = true;
134
135 for (i=0; i < 3; i++) {
136 dReal side = b->side[i] * REAL(0.5);
137
138 dist[i ] = side - q[i];
139 dist[i+3] = side + q[i];
140
141 if ((dist[i] < 0) || (dist[i+3] < 0)) {
142 inside = false;
143 }
144 }
145
146 // If point is inside the box, the depth is the smallest positive distance
147 // to any side
148
149 if (inside) {
150 dReal smallest_dist = (dReal) (unsigned) -1;
151
152 for (i=0; i < 6; i++) {
153 if (dist[i] < smallest_dist) smallest_dist = dist[i];
154 }
155
156 return smallest_dist;
157 }
158
159 // Otherwise, if point is outside the box, the depth is the largest
160 // distance to any side. This is an approximation to the 'proper'
161 // solution (the proper solution may be larger in some cases).
162
163 dReal largest_dist = 0;
164
165 for (i=0; i < 6; i++) {
166 if (dist[i] > largest_dist) largest_dist = dist[i];
167 }
168
169 return -largest_dist;
170}
171
172//****************************************************************************
173// box-box collision utility
174
175
176// find all the intersection points between the 2D rectangle with vertices
177// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
178// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
179//
180// the intersection points are returned as x,y pairs in the 'ret' array.
181// the number of intersection points is returned by the function (this will
182// be in the range 0 to 8).
183
184static int intersectRectQuad (dReal h[2], dReal p[8], dReal ret[16])
185{
186 // q (and r) contain nq (and nr) coordinate points for the current (and
187 // chopped) polygons
188 int nq=4,nr;
189 dReal buffer[16];
190 dReal *q = p;
191 dReal *r = ret;
192 for (int dir=0; dir <= 1; dir++) {
193 // direction notation: xy[0] = x axis, xy[1] = y axis
194 for (int sign=-1; sign <= 1; sign += 2) {
195 // chop q along the line xy[dir] = sign*h[dir]
196 dReal *pq = q;
197 dReal *pr = r;
198 nr = 0;
199 for (int i=nq; i > 0; i--) {
200 // go through all points in q and all lines between adjacent points
201 if (sign*pq[dir] < h[dir]) {
202 // this point is inside the chopping line
203 pr[0] = pq[0];
204 pr[1] = pq[1];
205 pr += 2;
206 nr++;
207 if (nr & 8) {
208 q = r;
209 goto done;
210 }
211 }
212 dReal *nextq = (i > 1) ? pq+2 : q;
213 if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
214 // this line crosses the chopping line
215 pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
216 (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
217 pr[dir] = sign*h[dir];
218 pr += 2;
219 nr++;
220 if (nr & 8) {
221 q = r;
222 goto done;
223 }
224 }
225 pq += 2;
226 }
227 q = r;
228 r = (q==ret) ? buffer : ret;
229 nq = nr;
230 }
231 }
232 done:
233 if (q != ret) memcpy (ret,q,nr*2*sizeof(dReal));
234 return nr;
235}
236
237
238// given n points in the plane (array p, of size 2*n), generate m points that
239// best represent the whole set. the definition of 'best' here is not
240// predetermined - the idea is to select points that give good box-box
241// collision detection behavior. the chosen point indexes are returned in the
242// array iret (of size m). 'i0' is always the first entry in the array.
243// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
244// in the range [0..n-1].
245
246void cullPoints (int n, dReal p[], int m, int i0, int iret[])
247{
248 // compute the centroid of the polygon in cx,cy
249 int i,j;
250 dReal a,cx,cy,q;
251 if (n==1) {
252 cx = p[0];
253 cy = p[1];
254 }
255 else if (n==2) {
256 cx = REAL(0.5)*(p[0] + p[2]);
257 cy = REAL(0.5)*(p[1] + p[3]);
258 }
259 else {
260 a = 0;
261 cx = 0;
262 cy = 0;
263 for (i=0; i<(n-1); i++) {
264 q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
265 a += q;
266 cx += q*(p[i*2]+p[i*2+2]);
267 cy += q*(p[i*2+1]+p[i*2+3]);
268 }
269 q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
270 a = dRecip(REAL(3.0)*(a+q));
271 cx = a*(cx + q*(p[n*2-2]+p[0]));
272 cy = a*(cy + q*(p[n*2-1]+p[1]));
273 }
274
275 // compute the angle of each point w.r.t. the centroid
276 dReal A[8];
277 for (i=0; i<n; i++) A[i] = dAtan2(p[i*2+1]-cy,p[i*2]-cx);
278
279 // search for points that have angles closest to A[i0] + i*(2*pi/m).
280 int avail[8];
281 for (i=0; i<n; i++) avail[i] = 1;
282 avail[i0] = 0;
283 iret[0] = i0;
284 iret++;
285 for (j=1; j<m; j++) {
286 a = dReal(j)*(2*M_PI/m) + A[i0];
287 if (a > M_PI) a -= 2*M_PI;
288 dReal maxdiff=1e9,diff;
289#ifndef dNODEBUG
290 *iret = i0; // iret is not allowed to keep this value
291#endif
292 for (i=0; i<n; i++) {
293 if (avail[i]) {
294 diff = dFabs (A[i]-a);
295 if (diff > M_PI) diff = 2*M_PI - diff;
296 if (diff < maxdiff) {
297 maxdiff = diff;
298 *iret = i;
299 }
300 }
301 }
302#ifndef dNODEBUG
303 dIASSERT (*iret != i0); // ensure iret got set
304#endif
305 avail[*iret] = 0;
306 iret++;
307 }
308}
309
310
311// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
312// generate contact points. this returns 0 if there is no contact otherwise
313// it returns the number of contacts generated.
314// `normal' returns the contact normal.
315// `depth' returns the maximum penetration depth along that normal.
316// `return_code' returns a number indicating the type of contact that was
317// detected:
318// 1,2,3 = box 2 intersects with a face of box 1
319// 4,5,6 = box 1 intersects with a face of box 2
320// 7..15 = edge-edge contact
321// `maxc' is the maximum number of contacts allowed to be generated, i.e.
322// the size of the `contact' array.
323// `contact' and `skip' are the contact array information provided to the
324// collision functions. this function only fills in the position and depth
325// fields.
326
327
328int dBoxBox (const dVector3 p1, const dMatrix3 R1,
329 const dVector3 side1, const dVector3 p2,
330 const dMatrix3 R2, const dVector3 side2,
331 dVector3 normal, dReal *depth, int *return_code,
332 int flags, dContactGeom *contact, int skip)
333{
334 const dReal fudge_factor = REAL(1.05);
335 dVector3 p,pp,normalC;
336 const dReal *normalR = 0;
337 dReal A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
338 Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l,expr1_val;
339 int i,j,invert_normal,code;
340
341 // get vector from centers of box 1 to box 2, relative to box 1
342 p[0] = p2[0] - p1[0];
343 p[1] = p2[1] - p1[1];
344 p[2] = p2[2] - p1[2];
345 dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
346
347 // get side lengths / 2
348 A[0] = side1[0]*REAL(0.5);
349 A[1] = side1[1]*REAL(0.5);
350 A[2] = side1[2]*REAL(0.5);
351 B[0] = side2[0]*REAL(0.5);
352 B[1] = side2[1]*REAL(0.5);
353 B[2] = side2[2]*REAL(0.5);
354
355 // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
356 R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
357 R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
358 R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
359
360 Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13);
361 Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23);
362 Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33);
363
364 // for all 15 possible separating axes:
365 // * see if the axis separates the boxes. if so, return 0.
366 // * find the depth of the penetration along the separating axis (s2)
367 // * if this is the largest depth so far, record it.
368 // the normal vector will be set to the separating axis with the smallest
369 // depth. note: normalR is set to point to a column of R1 or R2 if that is
370 // the smallest depth normal so far. otherwise normalR is 0 and normalC is
371 // set to a vector relative to body 1. invert_normal is 1 if the sign of
372 // the normal should be flipped.
373
374 do {
375#define TST(expr1,expr2,norm,cc) \
376 expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \
377 s2 = dFabs(expr1_val) - (expr2); \
378 if (s2 > 0) return 0; \
379 if (s2 > s) { \
380 s = s2; \
381 normalR = norm; \
382 invert_normal = ((expr1_val) < 0); \
383 code = (cc); \
384 if (flags & CONTACTS_UNIMPORTANT) break; \
385 }
386
387 s = -dInfinity;
388 invert_normal = 0;
389 code = 0;
390
391 // separating axis = u1,u2,u3
392 TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
393 TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
394 TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
395
396 // separating axis = v1,v2,v3
397 TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
398 TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
399 TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
400
401 // note: cross product axes need to be scaled when s is computed.
402 // normal (n1,n2,n3) is relative to box 1.
403#undef TST
404#define TST(expr1,expr2,n1,n2,n3,cc) \
405 expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \
406 s2 = dFabs(expr1_val) - (expr2); \
407 if (s2 > 0) return 0; \
408 l = dSqrt ((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
409 if (l > 0) { \
410 s2 /= l; \
411 if (s2*fudge_factor > s) { \
412 s = s2; \
413 normalR = 0; \
414 normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
415 invert_normal = ((expr1_val) < 0); \
416 code = (cc); \
417 if (flags & CONTACTS_UNIMPORTANT) break; \
418 } \
419 }
420
421 // separating axis = u1 x (v1,v2,v3)
422 TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
423 TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
424 TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
425
426 // separating axis = u2 x (v1,v2,v3)
427 TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
428 TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
429 TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
430
431 // separating axis = u3 x (v1,v2,v3)
432 TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
433 TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
434 TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
435#undef TST
436 } while (0);
437
438 if (!code) return 0;
439
440 // if we get to this point, the boxes interpenetrate. compute the normal
441 // in global coordinates.
442 if (normalR) {
443 normal[0] = normalR[0];
444 normal[1] = normalR[4];
445 normal[2] = normalR[8];
446 }
447 else {
448 dMULTIPLY0_331 (normal,R1,normalC);
449 }
450 if (invert_normal) {
451 normal[0] = -normal[0];
452 normal[1] = -normal[1];
453 normal[2] = -normal[2];
454 }
455 *depth = -s;
456
457 // compute contact point(s)
458
459 if (code > 6) {
460 // an edge from box 1 touches an edge from box 2.
461 // find a point pa on the intersecting edge of box 1
462 dVector3 pa;
463 dReal sign;
464 for (i=0; i<3; i++) pa[i] = p1[i];
465 for (j=0; j<3; j++) {
466 sign = (dDOT14(normal,R1+j) > 0) ? REAL(1.0) : REAL(-1.0);
467 for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
468 }
469
470 // find a point pb on the intersecting edge of box 2
471 dVector3 pb;
472 for (i=0; i<3; i++) pb[i] = p2[i];
473 for (j=0; j<3; j++) {
474 sign = (dDOT14(normal,R2+j) > 0) ? REAL(-1.0) : REAL(1.0);
475 for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
476 }
477
478 dReal alpha,beta;
479 dVector3 ua,ub;
480 for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
481 for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
482
483 dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
484 for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
485 for (i=0; i<3; i++) pb[i] += ub[i]*beta;
486
487 for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]);
488 contact[0].depth = *depth;
489 *return_code = code;
490 return 1;
491 }
492
493 // okay, we have a face-something intersection (because the separating
494 // axis is perpendicular to a face). define face 'a' to be the reference
495 // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
496 // the incident face (the closest face of the other box).
497
498 const dReal *Ra,*Rb,*pa,*pb,*Sa,*Sb;
499 if (code <= 3) {
500 Ra = R1;
501 Rb = R2;
502 pa = p1;
503 pb = p2;
504 Sa = A;
505 Sb = B;
506 }
507 else {
508 Ra = R2;
509 Rb = R1;
510 pa = p2;
511 pb = p1;
512 Sa = B;
513 Sb = A;
514 }
515
516 // nr = normal vector of reference face dotted with axes of incident box.
517 // anr = absolute values of nr.
518 dVector3 normal2,nr,anr;
519 if (code <= 3) {
520 normal2[0] = normal[0];
521 normal2[1] = normal[1];
522 normal2[2] = normal[2];
523 }
524 else {
525 normal2[0] = -normal[0];
526 normal2[1] = -normal[1];
527 normal2[2] = -normal[2];
528 }
529 dMULTIPLY1_331 (nr,Rb,normal2);
530 anr[0] = dFabs (nr[0]);
531 anr[1] = dFabs (nr[1]);
532 anr[2] = dFabs (nr[2]);
533
534 // find the largest compontent of anr: this corresponds to the normal
535 // for the indident face. the other axis numbers of the indicent face
536 // are stored in a1,a2.
537 int lanr,a1,a2;
538 if (anr[1] > anr[0]) {
539 if (anr[1] > anr[2]) {
540 a1 = 0;
541 lanr = 1;
542 a2 = 2;
543 }
544 else {
545 a1 = 0;
546 a2 = 1;
547 lanr = 2;
548 }
549 }
550 else {
551 if (anr[0] > anr[2]) {
552 lanr = 0;
553 a1 = 1;
554 a2 = 2;
555 }
556 else {
557 a1 = 0;
558 a2 = 1;
559 lanr = 2;
560 }
561 }
562
563 // compute center point of incident face, in reference-face coordinates
564 dVector3 center;
565 if (nr[lanr] < 0) {
566 for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
567 }
568 else {
569 for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
570 }
571
572 // find the normal and non-normal axis numbers of the reference box
573 int codeN,code1,code2;
574 if (code <= 3) codeN = code-1; else codeN = code-4;
575 if (codeN==0) {
576 code1 = 1;
577 code2 = 2;
578 }
579 else if (codeN==1) {
580 code1 = 0;
581 code2 = 2;
582 }
583 else {
584 code1 = 0;
585 code2 = 1;
586 }
587
588 // find the four corners of the incident face, in reference-face coordinates
589 dReal quad[8]; // 2D coordinate of incident face (x,y pairs)
590 dReal c1,c2,m11,m12,m21,m22;
591 c1 = dDOT14 (center,Ra+code1);
592 c2 = dDOT14 (center,Ra+code2);
593 // optimize this? - we have already computed this data above, but it is not
594 // stored in an easy-to-index format. for now it's quicker just to recompute
595 // the four dot products.
596 m11 = dDOT44 (Ra+code1,Rb+a1);
597 m12 = dDOT44 (Ra+code1,Rb+a2);
598 m21 = dDOT44 (Ra+code2,Rb+a1);
599 m22 = dDOT44 (Ra+code2,Rb+a2);
600 {
601 dReal k1 = m11*Sb[a1];
602 dReal k2 = m21*Sb[a1];
603 dReal k3 = m12*Sb[a2];
604 dReal k4 = m22*Sb[a2];
605 quad[0] = c1 - k1 - k3;
606 quad[1] = c2 - k2 - k4;
607 quad[2] = c1 - k1 + k3;
608 quad[3] = c2 - k2 + k4;
609 quad[4] = c1 + k1 + k3;
610 quad[5] = c2 + k2 + k4;
611 quad[6] = c1 + k1 - k3;
612 quad[7] = c2 + k2 - k4;
613 }
614
615 // find the size of the reference face
616 dReal rect[2];
617 rect[0] = Sa[code1];
618 rect[1] = Sa[code2];
619
620 // intersect the incident and reference faces
621 dReal ret[16];
622 int n = intersectRectQuad (rect,quad,ret);
623 if (n < 1) return 0; // this should never happen
624
625 // convert the intersection points into reference-face coordinates,
626 // and compute the contact position and depth for each point. only keep
627 // those points that have a positive (penetrating) depth. delete points in
628 // the 'ret' array as necessary so that 'point' and 'ret' correspond.
629 dReal point[3*8]; // penetrating contact points
630 dReal dep[8]; // depths for those points
631 dReal det1 = dRecip(m11*m22 - m12*m21);
632 m11 *= det1;
633 m12 *= det1;
634 m21 *= det1;
635 m22 *= det1;
636 int cnum = 0; // number of penetrating contact points found
637 for (j=0; j < n; j++) {
638 dReal k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
639 dReal k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
640 for (i=0; i<3; i++) point[cnum*3+i] =
641 center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
642 dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
643 if (dep[cnum] >= 0) {
644 ret[cnum*2] = ret[j*2];
645 ret[cnum*2+1] = ret[j*2+1];
646 cnum++;
647 if ((cnum | CONTACTS_UNIMPORTANT) == (flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
648 break;
649 }
650 }
651 }
652 if (cnum < 1) {
653 return 0; // this should not happen, yet does at times (demo_plane2d single precision).
654 }
655
656 // we can't generate more contacts than we actually have
657 int maxc = flags & NUMC_MASK;
658 if (maxc > cnum) maxc = cnum;
659 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
660
661 if (cnum <= maxc) {
662 // we have less contacts than we need, so we use them all
663 for (j=0; j < cnum; j++) {
664 dContactGeom *con = CONTACT(contact,skip*j);
665 for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
666 con->depth = dep[j];
667 }
668 }
669 else {
670 dIASSERT(!(flags & CONTACTS_UNIMPORTANT)); // cnum should be generated not greater than maxc so that "then" clause is executed
671 // we have more contacts than are wanted, some of them must be culled.
672 // find the deepest point, it is always the first contact.
673 int i1 = 0;
674 dReal maxdepth = dep[0];
675 for (i=1; i<cnum; i++) {
676 if (dep[i] > maxdepth) {
677 maxdepth = dep[i];
678 i1 = i;
679 }
680 }
681
682 int iret[8];
683 cullPoints (cnum,ret,maxc,i1,iret);
684
685 for (j=0; j < maxc; j++) {
686 dContactGeom *con = CONTACT(contact,skip*j);
687 for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
688 con->depth = dep[iret[j]];
689 }
690 cnum = maxc;
691 }
692
693 *return_code = code;
694 return cnum;
695}
696
697
698
699int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags,
700 dContactGeom *contact, int skip)
701{
702 dIASSERT (skip >= (int)sizeof(dContactGeom));
703 dIASSERT (o1->type == dBoxClass);
704 dIASSERT (o2->type == dBoxClass);
705 dIASSERT ((flags & NUMC_MASK) >= 1);
706
707 dVector3 normal;
708 dReal depth;
709 int code;
710 dxBox *b1 = (dxBox*) o1;
711 dxBox *b2 = (dxBox*) o2;
712 int num = dBoxBox (o1->final_posr->pos,o1->final_posr->R,b1->side, o2->final_posr->pos,o2->final_posr->R,b2->side,
713 normal,&depth,&code,flags,contact,skip);
714 for (int i=0; i<num; i++) {
715 CONTACT(contact,i*skip)->normal[0] = -normal[0];
716 CONTACT(contact,i*skip)->normal[1] = -normal[1];
717 CONTACT(contact,i*skip)->normal[2] = -normal[2];
718 CONTACT(contact,i*skip)->g1 = o1;
719 CONTACT(contact,i*skip)->g2 = o2;
720 }
721 return num;
722}
723
724
725int dCollideBoxPlane (dxGeom *o1, dxGeom *o2,
726 int flags, dContactGeom *contact, int skip)
727{
728 dIASSERT (skip >= (int)sizeof(dContactGeom));
729 dIASSERT (o1->type == dBoxClass);
730 dIASSERT (o2->type == dPlaneClass);
731 dIASSERT ((flags & NUMC_MASK) >= 1);
732
733 dxBox *box = (dxBox*) o1;
734 dxPlane *plane = (dxPlane*) o2;
735
736 contact->g1 = o1;
737 contact->g2 = o2;
738 int ret = 0;
739
740 //@@@ problem: using 4-vector (plane->p) as 3-vector (normal).
741 const dReal *R = o1->final_posr->R; // rotation of box
742 const dReal *n = plane->p; // normal vector
743
744 // project sides lengths along normal vector, get absolute values
745 dReal Q1 = dDOT14(n,R+0);
746 dReal Q2 = dDOT14(n,R+1);
747 dReal Q3 = dDOT14(n,R+2);
748 dReal A1 = box->side[0] * Q1;
749 dReal A2 = box->side[1] * Q2;
750 dReal A3 = box->side[2] * Q3;
751 dReal B1 = dFabs(A1);
752 dReal B2 = dFabs(A2);
753 dReal B3 = dFabs(A3);
754
755 // early exit test
756 dReal depth = plane->p[3] + REAL(0.5)*(B1+B2+B3) - dDOT(n,o1->final_posr->pos);
757 if (depth < 0) return 0;
758
759 // find number of contacts requested
760 int maxc = flags & NUMC_MASK;
761 // if (maxc < 1) maxc = 1; // an assertion is made on entry
762 if (maxc > 3) maxc = 3; // not more than 3 contacts per box allowed
763
764 // find deepest point
765 dVector3 p;
766 p[0] = o1->final_posr->pos[0];
767 p[1] = o1->final_posr->pos[1];
768 p[2] = o1->final_posr->pos[2];
769#define FOO(i,op) \
770 p[0] op REAL(0.5)*box->side[i] * R[0+i]; \
771 p[1] op REAL(0.5)*box->side[i] * R[4+i]; \
772 p[2] op REAL(0.5)*box->side[i] * R[8+i];
773#define BAR(i,iinc) if (A ## iinc > 0) { FOO(i,-=) } else { FOO(i,+=) }
774 BAR(0,1);
775 BAR(1,2);
776 BAR(2,3);
777#undef FOO
778#undef BAR
779
780 // the deepest point is the first contact point
781 contact->pos[0] = p[0];
782 contact->pos[1] = p[1];
783 contact->pos[2] = p[2];
784 contact->normal[0] = n[0];
785 contact->normal[1] = n[1];
786 contact->normal[2] = n[2];
787 contact->depth = depth;
788 ret = 1; // ret is number of contact points found so far
789 if (maxc == 1) goto done;
790
791 // get the second and third contact points by starting from `p' and going
792 // along the two sides with the smallest projected length.
793
794#define FOO(i,j,op) \
795 CONTACT(contact,i*skip)->pos[0] = p[0] op box->side[j] * R[0+j]; \
796 CONTACT(contact,i*skip)->pos[1] = p[1] op box->side[j] * R[4+j]; \
797 CONTACT(contact,i*skip)->pos[2] = p[2] op box->side[j] * R[8+j];
798#define BAR(ctact,side,sideinc) \
799 depth -= B ## sideinc; \
800 if (depth < 0) goto done; \
801 if (A ## sideinc > 0) { FOO(ctact,side,+); } else { FOO(ctact,side,-); } \
802 CONTACT(contact,ctact*skip)->depth = depth; \
803 ret++;
804
805 CONTACT(contact,skip)->normal[0] = n[0];
806 CONTACT(contact,skip)->normal[1] = n[1];
807 CONTACT(contact,skip)->normal[2] = n[2];
808 if (maxc == 3) {
809 CONTACT(contact,2*skip)->normal[0] = n[0];
810 CONTACT(contact,2*skip)->normal[1] = n[1];
811 CONTACT(contact,2*skip)->normal[2] = n[2];
812 }
813
814 if (B1 < B2) {
815 if (B3 < B1) goto use_side_3; else {
816 BAR(1,0,1); // use side 1
817 if (maxc == 2) goto done;
818 if (B2 < B3) goto contact2_2; else goto contact2_3;
819 }
820 }
821 else {
822 if (B3 < B2) {
823 use_side_3: // use side 3
824 BAR(1,2,3);
825 if (maxc == 2) goto done;
826 if (B1 < B2) goto contact2_1; else goto contact2_2;
827 }
828 else {
829 BAR(1,1,2); // use side 2
830 if (maxc == 2) goto done;
831 if (B1 < B3) goto contact2_1; else goto contact2_3;
832 }
833 }
834
835 contact2_1: BAR(2,0,1); goto done;
836 contact2_2: BAR(2,1,2); goto done;
837 contact2_3: BAR(2,2,3); goto done;
838#undef FOO
839#undef BAR
840
841 done:
842 for (int i=0; i<ret; i++) {
843 CONTACT(contact,i*skip)->g1 = o1;
844 CONTACT(contact,i*skip)->g2 = o2;
845 }
846 return ret;
847}
diff --git a/libraries/ode-0.9/ode/src/capsule.cpp b/libraries/ode-0.9/ode/src/capsule.cpp
deleted file mode 100644
index 5680baa..0000000
--- a/libraries/ode-0.9/ode/src/capsule.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45//****************************************************************************
46// capped cylinder public API
47
48dxCapsule::dxCapsule (dSpaceID space, dReal _radius, dReal _length) :
49 dxGeom (space,1)
50{
51 dAASSERT (_radius > 0 && _length > 0);
52 type = dCapsuleClass;
53 radius = _radius;
54 lz = _length;
55}
56
57
58void dxCapsule::computeAABB()
59{
60 const dMatrix3& R = final_posr->R;
61 const dVector3& pos = final_posr->pos;
62
63 dReal xrange = dFabs(R[2] * lz) * REAL(0.5) + radius;
64 dReal yrange = dFabs(R[6] * lz) * REAL(0.5) + radius;
65 dReal zrange = dFabs(R[10] * lz) * REAL(0.5) + radius;
66 aabb[0] = pos[0] - xrange;
67 aabb[1] = pos[0] + xrange;
68 aabb[2] = pos[1] - yrange;
69 aabb[3] = pos[1] + yrange;
70 aabb[4] = pos[2] - zrange;
71 aabb[5] = pos[2] + zrange;
72}
73
74
75dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length)
76{
77 return new dxCapsule (space,radius,length);
78}
79
80
81void dGeomCapsuleSetParams (dGeomID g, dReal radius, dReal length)
82{
83 dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
84 dAASSERT (radius > 0 && length > 0);
85 dxCapsule *c = (dxCapsule*) g;
86 c->radius = radius;
87 c->lz = length;
88 dGeomMoved (g);
89}
90
91
92void dGeomCapsuleGetParams (dGeomID g, dReal *radius, dReal *length)
93{
94 dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
95 dxCapsule *c = (dxCapsule*) g;
96 *radius = c->radius;
97 *length = c->lz;
98}
99
100
101dReal dGeomCapsulePointDepth (dGeomID g, dReal x, dReal y, dReal z)
102{
103 dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
104 g->recomputePosr();
105 dxCapsule *c = (dxCapsule*) g;
106
107 const dReal* R = g->final_posr->R;
108 const dReal* pos = g->final_posr->pos;
109
110 dVector3 a;
111 a[0] = x - pos[0];
112 a[1] = y - pos[1];
113 a[2] = z - pos[2];
114 dReal beta = dDOT14(a,R+2);
115 dReal lz2 = c->lz*REAL(0.5);
116 if (beta < -lz2) beta = -lz2;
117 else if (beta > lz2) beta = lz2;
118 a[0] = c->final_posr->pos[0] + beta*R[0*4+2];
119 a[1] = c->final_posr->pos[1] + beta*R[1*4+2];
120 a[2] = c->final_posr->pos[2] + beta*R[2*4+2];
121 return c->radius -
122 dSqrt ((x-a[0])*(x-a[0]) + (y-a[1])*(y-a[1]) + (z-a[2])*(z-a[2]));
123}
124
125
126
127int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags,
128 dContactGeom *contact, int skip)
129{
130 dIASSERT (skip >= (int)sizeof(dContactGeom));
131 dIASSERT (o1->type == dCapsuleClass);
132 dIASSERT (o2->type == dSphereClass);
133 dIASSERT ((flags & NUMC_MASK) >= 1);
134
135 dxCapsule *ccyl = (dxCapsule*) o1;
136 dxSphere *sphere = (dxSphere*) o2;
137
138 contact->g1 = o1;
139 contact->g2 = o2;
140
141 // find the point on the cylinder axis that is closest to the sphere
142 dReal alpha =
143 o1->final_posr->R[2] * (o2->final_posr->pos[0] - o1->final_posr->pos[0]) +
144 o1->final_posr->R[6] * (o2->final_posr->pos[1] - o1->final_posr->pos[1]) +
145 o1->final_posr->R[10] * (o2->final_posr->pos[2] - o1->final_posr->pos[2]);
146 dReal lz2 = ccyl->lz * REAL(0.5);
147 if (alpha > lz2) alpha = lz2;
148 if (alpha < -lz2) alpha = -lz2;
149
150 // collide the spheres
151 dVector3 p;
152 p[0] = o1->final_posr->pos[0] + alpha * o1->final_posr->R[2];
153 p[1] = o1->final_posr->pos[1] + alpha * o1->final_posr->R[6];
154 p[2] = o1->final_posr->pos[2] + alpha * o1->final_posr->R[10];
155 return dCollideSpheres (p,ccyl->radius,o2->final_posr->pos,sphere->radius,contact);
156}
157
158
159int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags,
160 dContactGeom *contact, int skip)
161{
162 dIASSERT (skip >= (int)sizeof(dContactGeom));
163 dIASSERT (o1->type == dCapsuleClass);
164 dIASSERT (o2->type == dBoxClass);
165 dIASSERT ((flags & NUMC_MASK) >= 1);
166
167 dxCapsule *cyl = (dxCapsule*) o1;
168 dxBox *box = (dxBox*) o2;
169
170 contact->g1 = o1;
171 contact->g2 = o2;
172
173 // get p1,p2 = cylinder axis endpoints, get radius
174 dVector3 p1,p2;
175 dReal clen = cyl->lz * REAL(0.5);
176 p1[0] = o1->final_posr->pos[0] + clen * o1->final_posr->R[2];
177 p1[1] = o1->final_posr->pos[1] + clen * o1->final_posr->R[6];
178 p1[2] = o1->final_posr->pos[2] + clen * o1->final_posr->R[10];
179 p2[0] = o1->final_posr->pos[0] - clen * o1->final_posr->R[2];
180 p2[1] = o1->final_posr->pos[1] - clen * o1->final_posr->R[6];
181 p2[2] = o1->final_posr->pos[2] - clen * o1->final_posr->R[10];
182 dReal radius = cyl->radius;
183
184 // copy out box center, rotation matrix, and side array
185 dReal *c = o2->final_posr->pos;
186 dReal *R = o2->final_posr->R;
187 const dReal *side = box->side;
188
189 // get the closest point between the cylinder axis and the box
190 dVector3 pl,pb;
191 dClosestLineBoxPoints (p1,p2,c,R,side,pl,pb);
192
193 // generate contact point
194 return dCollideSpheres (pl,radius,pb,0,contact);
195}
196
197
198int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2,
199 int flags, dContactGeom *contact, int skip)
200{
201 dIASSERT (skip >= (int)sizeof(dContactGeom));
202 dIASSERT (o1->type == dCapsuleClass);
203 dIASSERT (o2->type == dCapsuleClass);
204 dIASSERT ((flags & NUMC_MASK) >= 1);
205
206 int i;
207 const dReal tolerance = REAL(1e-5);
208
209 dxCapsule *cyl1 = (dxCapsule*) o1;
210 dxCapsule *cyl2 = (dxCapsule*) o2;
211
212 contact->g1 = o1;
213 contact->g2 = o2;
214
215 // copy out some variables, for convenience
216 dReal lz1 = cyl1->lz * REAL(0.5);
217 dReal lz2 = cyl2->lz * REAL(0.5);
218 dReal *pos1 = o1->final_posr->pos;
219 dReal *pos2 = o2->final_posr->pos;
220 dReal axis1[3],axis2[3];
221 axis1[0] = o1->final_posr->R[2];
222 axis1[1] = o1->final_posr->R[6];
223 axis1[2] = o1->final_posr->R[10];
224 axis2[0] = o2->final_posr->R[2];
225 axis2[1] = o2->final_posr->R[6];
226 axis2[2] = o2->final_posr->R[10];
227
228 // if the cylinder axes are close to parallel, we'll try to detect up to
229 // two contact points along the body of the cylinder. if we can't find any
230 // points then we'll fall back to the closest-points algorithm. note that
231 // we are not treating this special case for reasons of degeneracy, but
232 // because we want two contact points in some situations. the closet-points
233 // algorithm is robust in all casts, but it can return only one contact.
234
235 dVector3 sphere1,sphere2;
236 dReal a1a2 = dDOT (axis1,axis2);
237 dReal det = REAL(1.0)-a1a2*a1a2;
238 if (det < tolerance) {
239 // the cylinder axes (almost) parallel, so we will generate up to two
240 // contacts. alpha1 and alpha2 (line position parameters) are related by:
241 // alpha2 = alpha1 + (pos1-pos2)'*axis1 (if axis1==axis2)
242 // or alpha2 = -(alpha1 + (pos1-pos2)'*axis1) (if axis1==-axis2)
243 // first compute where the two cylinders overlap in alpha1 space:
244 if (a1a2 < 0) {
245 axis2[0] = -axis2[0];
246 axis2[1] = -axis2[1];
247 axis2[2] = -axis2[2];
248 }
249 dReal q[3];
250 for (i=0; i<3; i++) q[i] = pos1[i]-pos2[i];
251 dReal k = dDOT (axis1,q);
252 dReal a1lo = -lz1;
253 dReal a1hi = lz1;
254 dReal a2lo = -lz2 - k;
255 dReal a2hi = lz2 - k;
256 dReal lo = (a1lo > a2lo) ? a1lo : a2lo;
257 dReal hi = (a1hi < a2hi) ? a1hi : a2hi;
258 if (lo <= hi) {
259 int num_contacts = flags & NUMC_MASK;
260 if (num_contacts >= 2 && lo < hi) {
261 // generate up to two contacts. if one of those contacts is
262 // not made, fall back on the one-contact strategy.
263 for (i=0; i<3; i++) sphere1[i] = pos1[i] + lo*axis1[i];
264 for (i=0; i<3; i++) sphere2[i] = pos2[i] + (lo+k)*axis2[i];
265 int n1 = dCollideSpheres (sphere1,cyl1->radius,
266 sphere2,cyl2->radius,contact);
267 if (n1) {
268 for (i=0; i<3; i++) sphere1[i] = pos1[i] + hi*axis1[i];
269 for (i=0; i<3; i++) sphere2[i] = pos2[i] + (hi+k)*axis2[i];
270 dContactGeom *c2 = CONTACT(contact,skip);
271 int n2 = dCollideSpheres (sphere1,cyl1->radius,
272 sphere2,cyl2->radius, c2);
273 if (n2) {
274 c2->g1 = o1;
275 c2->g2 = o2;
276 return 2;
277 }
278 }
279 }
280
281 // just one contact to generate, so put it in the middle of
282 // the range
283 dReal alpha1 = (lo + hi) * REAL(0.5);
284 dReal alpha2 = alpha1 + k;
285 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
286 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
287 return dCollideSpheres (sphere1,cyl1->radius,
288 sphere2,cyl2->radius,contact);
289 }
290 }
291
292 // use the closest point algorithm
293 dVector3 a1,a2,b1,b2;
294 a1[0] = o1->final_posr->pos[0] + axis1[0]*lz1;
295 a1[1] = o1->final_posr->pos[1] + axis1[1]*lz1;
296 a1[2] = o1->final_posr->pos[2] + axis1[2]*lz1;
297 a2[0] = o1->final_posr->pos[0] - axis1[0]*lz1;
298 a2[1] = o1->final_posr->pos[1] - axis1[1]*lz1;
299 a2[2] = o1->final_posr->pos[2] - axis1[2]*lz1;
300 b1[0] = o2->final_posr->pos[0] + axis2[0]*lz2;
301 b1[1] = o2->final_posr->pos[1] + axis2[1]*lz2;
302 b1[2] = o2->final_posr->pos[2] + axis2[2]*lz2;
303 b2[0] = o2->final_posr->pos[0] - axis2[0]*lz2;
304 b2[1] = o2->final_posr->pos[1] - axis2[1]*lz2;
305 b2[2] = o2->final_posr->pos[2] - axis2[2]*lz2;
306
307 dClosestLineSegmentPoints (a1,a2,b1,b2,sphere1,sphere2);
308 return dCollideSpheres (sphere1,cyl1->radius,sphere2,cyl2->radius,contact);
309}
310
311
312int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags,
313 dContactGeom *contact, int skip)
314{
315 dIASSERT (skip >= (int)sizeof(dContactGeom));
316 dIASSERT (o1->type == dCapsuleClass);
317 dIASSERT (o2->type == dPlaneClass);
318 dIASSERT ((flags & NUMC_MASK) >= 1);
319
320 dxCapsule *ccyl = (dxCapsule*) o1;
321 dxPlane *plane = (dxPlane*) o2;
322
323 // collide the deepest capping sphere with the plane
324 dReal sign = (dDOT14 (plane->p,o1->final_posr->R+2) > 0) ? REAL(-1.0) : REAL(1.0);
325 dVector3 p;
326 p[0] = o1->final_posr->pos[0] + o1->final_posr->R[2] * ccyl->lz * REAL(0.5) * sign;
327 p[1] = o1->final_posr->pos[1] + o1->final_posr->R[6] * ccyl->lz * REAL(0.5) * sign;
328 p[2] = o1->final_posr->pos[2] + o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign;
329
330 dReal k = dDOT (p,plane->p);
331 dReal depth = plane->p[3] - k + ccyl->radius;
332 if (depth < 0) return 0;
333 contact->normal[0] = plane->p[0];
334 contact->normal[1] = plane->p[1];
335 contact->normal[2] = plane->p[2];
336 contact->pos[0] = p[0] - plane->p[0] * ccyl->radius;
337 contact->pos[1] = p[1] - plane->p[1] * ccyl->radius;
338 contact->pos[2] = p[2] - plane->p[2] * ccyl->radius;
339 contact->depth = depth;
340
341 int ncontacts = 1;
342 if ((flags & NUMC_MASK) >= 2) {
343 // collide the other capping sphere with the plane
344 p[0] = o1->final_posr->pos[0] - o1->final_posr->R[2] * ccyl->lz * REAL(0.5) * sign;
345 p[1] = o1->final_posr->pos[1] - o1->final_posr->R[6] * ccyl->lz * REAL(0.5) * sign;
346 p[2] = o1->final_posr->pos[2] - o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign;
347
348 k = dDOT (p,plane->p);
349 depth = plane->p[3] - k + ccyl->radius;
350 if (depth >= 0) {
351 dContactGeom *c2 = CONTACT(contact,skip);
352 c2->normal[0] = plane->p[0];
353 c2->normal[1] = plane->p[1];
354 c2->normal[2] = plane->p[2];
355 c2->pos[0] = p[0] - plane->p[0] * ccyl->radius;
356 c2->pos[1] = p[1] - plane->p[1] * ccyl->radius;
357 c2->pos[2] = p[2] - plane->p[2] * ccyl->radius;
358 c2->depth = depth;
359 ncontacts = 2;
360 }
361 }
362
363 for (int i=0; i < ncontacts; i++) {
364 CONTACT(contact,i*skip)->g1 = o1;
365 CONTACT(contact,i*skip)->g2 = o2;
366 }
367 return ncontacts;
368}
369
diff --git a/libraries/ode-0.9/ode/src/collision_cylinder_box.cpp b/libraries/ode-0.9/ode/src/collision_cylinder_box.cpp
deleted file mode 100644
index eb14c72..0000000
--- a/libraries/ode-0.9/ode/src/collision_cylinder_box.cpp
+++ /dev/null
@@ -1,1007 +0,0 @@
1/*************************************************************************
2* *
3* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4* All rights reserved. Email: russ@q12.org Web: www.q12.org *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of EITHER: *
8* (1) The GNU Lesser General Public License as published by the Free *
9* Software Foundation; either version 2.1 of the License, or (at *
10* your option) any later version. The text of the GNU Lesser *
11* General Public License is included with this library in the *
12* file LICENSE.TXT. *
13* (2) The BSD-style license that is included with this library in *
14* the file LICENSE-BSD.TXT. *
15* *
16* This library is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20* *
21*************************************************************************/
22
23/*
24 * Cylinder-box collider by Alen Ladavac
25 * Ported to ODE by Nguyen Binh
26 */
27
28#include <ode/collision.h>
29#include <ode/matrix.h>
30#include <ode/rotation.h>
31#include <ode/odemath.h>
32#include "collision_util.h"
33
34static const int MAX_CYLBOX_CLIP_POINTS = 16;
35static const int nCYLINDER_AXIS = 2;
36// Number of segment of cylinder base circle.
37// Must be divisible by 4.
38static const int nCYLINDER_SEGMENT = 8;
39
40#define MAX_FLOAT dInfinity
41
42// Data that passed through the collider's functions
43typedef struct _sCylinderBoxData
44{
45 // cylinder parameters
46 dMatrix3 mCylinderRot;
47 dVector3 vCylinderPos;
48 dVector3 vCylinderAxis;
49 dReal fCylinderRadius;
50 dReal fCylinderSize;
51 dVector3 avCylinderNormals[nCYLINDER_SEGMENT];
52
53 // box parameters
54
55 dMatrix3 mBoxRot;
56 dVector3 vBoxPos;
57 dVector3 vBoxHalfSize;
58 // box vertices array : 8 vertices
59 dVector3 avBoxVertices[8];
60
61 // global collider data
62 dVector3 vDiff;
63 dVector3 vNormal;
64 dReal fBestDepth;
65 dReal fBestrb;
66 dReal fBestrc;
67 int iBestAxis;
68
69 // contact data
70 dVector3 vEp0, vEp1;
71 dReal fDepth0, fDepth1;
72
73 // ODE stuff
74 dGeomID gBox;
75 dGeomID gCylinder;
76 dContactGeom* gContact;
77 int iFlags;
78 int iSkip;
79 int nContacts;
80
81} sCylinderBoxData;
82
83
84// initialize collision data
85void _cldInitCylinderBox(sCylinderBoxData& cData)
86{
87 // get cylinder position, orientation
88 const dReal* pRotCyc = dGeomGetRotation(cData.gCylinder);
89 dMatrix3Copy(pRotCyc,cData.mCylinderRot);
90
91 const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(cData.gCylinder);
92 dVector3Copy(*pPosCyc,cData.vCylinderPos);
93
94 dMat3GetCol(cData.mCylinderRot,nCYLINDER_AXIS,cData.vCylinderAxis);
95
96 // get cylinder radius and size
97 dGeomCylinderGetParams(cData.gCylinder,&cData.fCylinderRadius,&cData.fCylinderSize);
98
99 // get box position, orientation, size
100 const dReal* pRotBox = dGeomGetRotation(cData.gBox);
101 dMatrix3Copy(pRotBox,cData.mBoxRot);
102 const dVector3* pPosBox = (const dVector3*)dGeomGetPosition(cData.gBox);
103 dVector3Copy(*pPosBox,cData.vBoxPos);
104
105 dGeomBoxGetLengths(cData.gBox, cData.vBoxHalfSize);
106 cData.vBoxHalfSize[0] *= REAL(0.5);
107 cData.vBoxHalfSize[1] *= REAL(0.5);
108 cData.vBoxHalfSize[2] *= REAL(0.5);
109
110 // vertex 0
111 cData.avBoxVertices[0][0] = -cData.vBoxHalfSize[0];
112 cData.avBoxVertices[0][1] = cData.vBoxHalfSize[1];
113 cData.avBoxVertices[0][2] = -cData.vBoxHalfSize[2];
114
115 // vertex 1
116 cData.avBoxVertices[1][0] = cData.vBoxHalfSize[0];
117 cData.avBoxVertices[1][1] = cData.vBoxHalfSize[1];
118 cData.avBoxVertices[1][2] = -cData.vBoxHalfSize[2];
119
120 // vertex 2
121 cData.avBoxVertices[2][0] = -cData.vBoxHalfSize[0];
122 cData.avBoxVertices[2][1] = -cData.vBoxHalfSize[1];
123 cData.avBoxVertices[2][2] = -cData.vBoxHalfSize[2];
124
125 // vertex 3
126 cData.avBoxVertices[3][0] = cData.vBoxHalfSize[0];
127 cData.avBoxVertices[3][1] = -cData.vBoxHalfSize[1];
128 cData.avBoxVertices[3][2] = -cData.vBoxHalfSize[2];
129
130 // vertex 4
131 cData.avBoxVertices[4][0] = cData.vBoxHalfSize[0];
132 cData.avBoxVertices[4][1] = cData.vBoxHalfSize[1];
133 cData.avBoxVertices[4][2] = cData.vBoxHalfSize[2];
134
135 // vertex 5
136 cData.avBoxVertices[5][0] = cData.vBoxHalfSize[0];
137 cData.avBoxVertices[5][1] = -cData.vBoxHalfSize[1];
138 cData.avBoxVertices[5][2] = cData.vBoxHalfSize[2];
139
140 // vertex 6
141 cData.avBoxVertices[6][0] = -cData.vBoxHalfSize[0];
142 cData.avBoxVertices[6][1] = -cData.vBoxHalfSize[1];
143 cData.avBoxVertices[6][2] = cData.vBoxHalfSize[2];
144
145 // vertex 7
146 cData.avBoxVertices[7][0] = -cData.vBoxHalfSize[0];
147 cData.avBoxVertices[7][1] = cData.vBoxHalfSize[1];
148 cData.avBoxVertices[7][2] = cData.vBoxHalfSize[2];
149
150 // temp index
151 int i = 0;
152 dVector3 vTempBoxVertices[8];
153 // transform vertices in absolute space
154 for(i=0; i < 8; i++)
155 {
156 dMultiplyMat3Vec3(cData.mBoxRot,cData.avBoxVertices[i], vTempBoxVertices[i]);
157 dVector3Add(vTempBoxVertices[i], cData.vBoxPos, cData.avBoxVertices[i]);
158 }
159
160 // find relative position
161 dVector3Subtract(cData.vCylinderPos,cData.vBoxPos,cData.vDiff);
162 cData.fBestDepth = MAX_FLOAT;
163 cData.vNormal[0] = REAL(0.0);
164 cData.vNormal[1] = REAL(0.0);
165 cData.vNormal[2] = REAL(0.0);
166
167 // calculate basic angle for nCYLINDER_SEGMENT-gon
168 dReal fAngle = M_PI/nCYLINDER_SEGMENT;
169
170 // calculate angle increment
171 dReal fAngleIncrement = fAngle * REAL(2.0);
172
173 // calculate nCYLINDER_SEGMENT-gon points
174 for(i = 0; i < nCYLINDER_SEGMENT; i++)
175 {
176 cData.avCylinderNormals[i][0] = -dCos(fAngle);
177 cData.avCylinderNormals[i][1] = -dSin(fAngle);
178 cData.avCylinderNormals[i][2] = 0;
179
180 fAngle += fAngleIncrement;
181 }
182
183 cData.fBestrb = 0;
184 cData.fBestrc = 0;
185 cData.iBestAxis = 0;
186 cData.nContacts = 0;
187
188}
189
190// test for given separating axis
191int _cldTestAxis(sCylinderBoxData& cData, dVector3& vInputNormal, int iAxis )
192{
193 // check length of input normal
194 dReal fL = dVector3Length(vInputNormal);
195 // if not long enough
196 if ( fL < REAL(1e-5) )
197 {
198 // do nothing
199 return 1;
200 }
201
202 // otherwise make it unit for sure
203 dNormalize3(vInputNormal);
204
205 // project box and Cylinder on mAxis
206 dReal fdot1 = dVector3Dot(cData.vCylinderAxis, vInputNormal);
207
208 dReal frc;
209
210 if (fdot1 > REAL(1.0))
211 {
212 fdot1 = REAL(1.0);
213 frc = dFabs(cData.fCylinderSize*REAL(0.5));
214 }
215
216 // project box and capsule on iAxis
217 frc = dFabs( fdot1 * (cData.fCylinderSize*REAL(0.5))) + cData.fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1));
218
219 dVector3 vTemp1;
220 dReal frb = REAL(0.0);
221
222 dMat3GetCol(cData.mBoxRot,0,vTemp1);
223 frb = dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[0];
224
225 dMat3GetCol(cData.mBoxRot,1,vTemp1);
226 frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[1];
227
228 dMat3GetCol(cData.mBoxRot,2,vTemp1);
229 frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[2];
230
231 // project their distance on separating axis
232 dReal fd = dVector3Dot(cData.vDiff,vInputNormal);
233
234 // if they do not overlap exit, we have no intersection
235 if ( dFabs(fd) > frc+frb )
236 {
237 return 0;
238 }
239
240 // get depth
241 dReal fDepth = - dFabs(fd) + (frc+frb);
242
243 // get maximum depth
244 if ( fDepth < cData.fBestDepth )
245 {
246 cData.fBestDepth = fDepth;
247 dVector3Copy(vInputNormal,cData.vNormal);
248 cData.iBestAxis = iAxis;
249 cData.fBestrb = frb;
250 cData.fBestrc = frc;
251
252 // flip normal if interval is wrong faced
253 if (fd > 0)
254 {
255 dVector3Inv(cData.vNormal);
256 }
257 }
258
259 return 1;
260}
261
262
263// check for separation between box edge and cylinder circle edge
264int _cldTestEdgeCircleAxis( sCylinderBoxData& cData,
265 const dVector3 &vCenterPoint,
266 const dVector3 &vVx0, const dVector3 &vVx1,
267 int iAxis )
268{
269 // calculate direction of edge
270 dVector3 vDirEdge;
271 dVector3Subtract(vVx1,vVx0,vDirEdge);
272 dNormalize3(vDirEdge);
273 // starting point of edge
274 dVector3 vEStart;
275 dVector3Copy(vVx0,vEStart);;
276
277 // calculate angle cosine between cylinder axis and edge
278 dReal fdot2 = dVector3Dot (vDirEdge,cData.vCylinderAxis);
279
280 // if edge is perpendicular to cylinder axis
281 if(dFabs(fdot2) < REAL(1e-5))
282 {
283 // this can't be separating axis, because edge is parallel to circle plane
284 return 1;
285 }
286
287 // find point of intersection between edge line and circle plane
288 dVector3 vTemp1;
289 dVector3Subtract(vCenterPoint,vEStart,vTemp1);
290 dReal fdot1 = dVector3Dot(vTemp1,cData.vCylinderAxis);
291 dVector3 vpnt;
292 vpnt[0]= vEStart[0] + vDirEdge[0] * (fdot1/fdot2);
293 vpnt[1]= vEStart[1] + vDirEdge[1] * (fdot1/fdot2);
294 vpnt[2]= vEStart[2] + vDirEdge[2] * (fdot1/fdot2);
295
296 // find tangent vector on circle with same center (vCenterPoint) that
297 // touches point of intersection (vpnt)
298 dVector3 vTangent;
299 dVector3Subtract(vCenterPoint,vpnt,vTemp1);
300 dVector3Cross(vTemp1,cData.vCylinderAxis,vTangent);
301
302 // find vector orthogonal both to tangent and edge direction
303 dVector3 vAxis;
304 dVector3Cross(vTangent,vDirEdge,vAxis);
305
306 // use that vector as separating axis
307 return _cldTestAxis( cData, vAxis, iAxis );
308}
309
310// Test separating axis for collision
311int _cldTestSeparatingAxes(sCylinderBoxData& cData)
312{
313 // reset best axis
314 cData.fBestDepth = MAX_FLOAT;
315 cData.iBestAxis = 0;
316 cData.fBestrb = 0;
317 cData.fBestrc = 0;
318 cData.nContacts = 0;
319
320 dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};
321
322 // Epsilon value for checking axis vector length
323 const dReal fEpsilon = REAL(1e-6);
324
325 // axis A0
326 dMat3GetCol(cData.mBoxRot, 0 , vAxis);
327 if (!_cldTestAxis( cData, vAxis, 1 ))
328 {
329 return 0;
330 }
331
332 // axis A1
333 dMat3GetCol(cData.mBoxRot, 1 , vAxis);
334 if (!_cldTestAxis( cData, vAxis, 2 ))
335 {
336 return 0;
337 }
338
339 // axis A2
340 dMat3GetCol(cData.mBoxRot, 2 , vAxis);
341 if (!_cldTestAxis( cData, vAxis, 3 ))
342 {
343 return 0;
344 }
345
346 // axis C - Cylinder Axis
347 //vAxis = vCylinderAxis;
348 dVector3Copy(cData.vCylinderAxis , vAxis);
349 if (!_cldTestAxis( cData, vAxis, 4 ))
350 {
351 return 0;
352 }
353
354 // axis CxA0
355 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 0 ));
356 dVector3CrossMat3Col(cData.mBoxRot, 0 ,cData.vCylinderAxis, vAxis);
357 if(dVector3Length2( vAxis ) > fEpsilon )
358 {
359 if (!_cldTestAxis( cData, vAxis, 5 ))
360 {
361 return 0;
362 }
363 }
364
365 // axis CxA1
366 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 1 ));
367 dVector3CrossMat3Col(cData.mBoxRot, 1 ,cData.vCylinderAxis, vAxis);
368 if(dVector3Length2( vAxis ) > fEpsilon )
369 {
370 if (!_cldTestAxis( cData, vAxis, 6 ))
371 {
372 return 0;
373 }
374 }
375
376 // axis CxA2
377 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 2 ));
378 dVector3CrossMat3Col(cData.mBoxRot, 2 ,cData.vCylinderAxis, vAxis);
379 if(dVector3Length2( vAxis ) > fEpsilon )
380 {
381 if (!_cldTestAxis( cData, vAxis, 7 ))
382 {
383 return 0;
384 }
385 }
386
387 int i = 0;
388 dVector3 vTemp1;
389 dVector3 vTemp2;
390 // here we check box's vertices axis
391 for(i=0; i< 8; i++)
392 {
393 //vAxis = ( vCylinderAxis cross (cData.avBoxVertices[i] - vCylinderPos));
394 dVector3Subtract(cData.avBoxVertices[i],cData.vCylinderPos,vTemp1);
395 dVector3Cross(cData.vCylinderAxis,vTemp1,vTemp2);
396 //vAxis = ( vCylinderAxis cross vAxis );
397 dVector3Cross(cData.vCylinderAxis,vTemp2,vAxis);
398 if(dVector3Length2( vAxis ) > fEpsilon )
399 {
400 if (!_cldTestAxis( cData, vAxis, 8 + i ))
401 {
402 return 0;
403 }
404 }
405 }
406
407 // ************************************
408 // this is defined for first 12 axes
409 // normal of plane that contains top circle of cylinder
410 // center of top circle of cylinder
411 dVector3 vcc;
412 vcc[0] = (cData.vCylinderPos)[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
413 vcc[1] = (cData.vCylinderPos)[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
414 vcc[2] = (cData.vCylinderPos)[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
415 // ************************************
416
417 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[0], 16))
418 {
419 return 0;
420 }
421
422 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[3], 17))
423 {
424 return 0;
425 }
426
427 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[3], 18))
428 {
429 return 0;
430 }
431
432 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[0], 19))
433 {
434 return 0;
435 }
436
437
438 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[1], 20))
439 {
440 return 0;
441 }
442
443 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[7], 21))
444 {
445 return 0;
446 }
447
448 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[0], cData.avBoxVertices[7], 22))
449 {
450 return 0;
451 }
452
453 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[3], 23))
454 {
455 return 0;
456 }
457
458 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[6], 24))
459 {
460 return 0;
461 }
462
463 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[6], 25))
464 {
465 return 0;
466 }
467
468 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[5], 26))
469 {
470 return 0;
471 }
472
473 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[6], cData.avBoxVertices[7], 27))
474 {
475 return 0;
476 }
477
478 // ************************************
479 // this is defined for second 12 axes
480 // normal of plane that contains bottom circle of cylinder
481 // center of bottom circle of cylinder
482 // vcc = vCylinderPos - vCylinderAxis*(fCylinderSize*REAL(0.5));
483 vcc[0] = (cData.vCylinderPos)[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
484 vcc[1] = (cData.vCylinderPos)[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
485 vcc[2] = (cData.vCylinderPos)[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
486 // ************************************
487
488 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[0], 28))
489 {
490 return 0;
491 }
492
493 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[3], 29))
494 {
495 return 0;
496 }
497
498 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[3], 30))
499 {
500 return 0;
501 }
502
503 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[0], 31))
504 {
505 return 0;
506 }
507
508 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[1], 32))
509 {
510 return 0;
511 }
512
513 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[7], 33))
514 {
515 return 0;
516 }
517
518 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[0], cData.avBoxVertices[7], 34))
519 {
520 return 0;
521 }
522
523 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[3], 35))
524 {
525 return 0;
526 }
527
528 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[6], 36))
529 {
530 return 0;
531 }
532
533 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[6], 37))
534 {
535 return 0;
536 }
537
538 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[5], 38))
539 {
540 return 0;
541 }
542
543 if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[6], cData.avBoxVertices[7], 39))
544 {
545 return 0;
546 }
547
548 return 1;
549}
550
551int _cldClipCylinderToBox(sCylinderBoxData& cData)
552{
553 dIASSERT(cData.nContacts != (cData.iFlags & NUMC_MASK));
554
555 // calculate that vector perpendicular to cylinder axis which closes lowest angle with collision normal
556 dVector3 vN;
557 dReal fTemp1 = dVector3Dot(cData.vCylinderAxis,cData.vNormal);
558 vN[0] = cData.vNormal[0] - cData.vCylinderAxis[0]*fTemp1;
559 vN[1] = cData.vNormal[1] - cData.vCylinderAxis[1]*fTemp1;
560 vN[2] = cData.vNormal[2] - cData.vCylinderAxis[2]*fTemp1;
561
562 // normalize that vector
563 dNormalize3(vN);
564
565 // translate cylinder end points by the vector
566 dVector3 vCposTrans;
567 vCposTrans[0] = cData.vCylinderPos[0] + vN[0] * cData.fCylinderRadius;
568 vCposTrans[1] = cData.vCylinderPos[1] + vN[1] * cData.fCylinderRadius;
569 vCposTrans[2] = cData.vCylinderPos[2] + vN[2] * cData.fCylinderRadius;
570
571 cData.vEp0[0] = vCposTrans[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
572 cData.vEp0[1] = vCposTrans[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
573 cData.vEp0[2] = vCposTrans[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
574
575 cData.vEp1[0] = vCposTrans[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
576 cData.vEp1[1] = vCposTrans[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
577 cData.vEp1[2] = vCposTrans[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
578
579 // transform edge points in box space
580 cData.vEp0[0] -= cData.vBoxPos[0];
581 cData.vEp0[1] -= cData.vBoxPos[1];
582 cData.vEp0[2] -= cData.vBoxPos[2];
583
584 cData.vEp1[0] -= cData.vBoxPos[0];
585 cData.vEp1[1] -= cData.vBoxPos[1];
586 cData.vEp1[2] -= cData.vBoxPos[2];
587
588 dVector3 vTemp1;
589 // clip the edge to box
590 dVector4 plPlane;
591 // plane 0 +x
592 dMat3GetCol(cData.mBoxRot,0,vTemp1);
593 dConstructPlane(vTemp1,cData.vBoxHalfSize[0],plPlane);
594 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
595 {
596 return 0;
597 }
598
599 // plane 1 +y
600 dMat3GetCol(cData.mBoxRot,1,vTemp1);
601 dConstructPlane(vTemp1,cData.vBoxHalfSize[1],plPlane);
602 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
603 {
604 return 0;
605 }
606
607 // plane 2 +z
608 dMat3GetCol(cData.mBoxRot,2,vTemp1);
609 dConstructPlane(vTemp1,cData.vBoxHalfSize[2],plPlane);
610 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
611 {
612 return 0;
613 }
614
615 // plane 3 -x
616 dMat3GetCol(cData.mBoxRot,0,vTemp1);
617 dVector3Inv(vTemp1);
618 dConstructPlane(vTemp1,cData.vBoxHalfSize[0],plPlane);
619 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
620 {
621 return 0;
622 }
623
624 // plane 4 -y
625 dMat3GetCol(cData.mBoxRot,1,vTemp1);
626 dVector3Inv(vTemp1);
627 dConstructPlane(vTemp1,cData.vBoxHalfSize[1],plPlane);
628 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
629 {
630 return 0;
631 }
632
633 // plane 5 -z
634 dMat3GetCol(cData.mBoxRot,2,vTemp1);
635 dVector3Inv(vTemp1);
636 dConstructPlane(vTemp1,cData.vBoxHalfSize[2],plPlane);
637 if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane ))
638 {
639 return 0;
640 }
641
642 // calculate depths for both contact points
643 cData.fDepth0 = cData.fBestrb + dVector3Dot(cData.vEp0, cData.vNormal);
644 cData.fDepth1 = cData.fBestrb + dVector3Dot(cData.vEp1, cData.vNormal);
645
646 // clamp depths to 0
647 if(cData.fDepth0<0)
648 {
649 cData.fDepth0 = REAL(0.0);
650 }
651
652 if(cData.fDepth1<0)
653 {
654 cData.fDepth1 = REAL(0.0);
655 }
656
657 // back transform edge points from box to absolute space
658 cData.vEp0[0] += cData.vBoxPos[0];
659 cData.vEp0[1] += cData.vBoxPos[1];
660 cData.vEp0[2] += cData.vBoxPos[2];
661
662 cData.vEp1[0] += cData.vBoxPos[0];
663 cData.vEp1[1] += cData.vBoxPos[1];
664 cData.vEp1[2] += cData.vBoxPos[2];
665
666 dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
667 Contact0->depth = cData.fDepth0;
668 dVector3Copy(cData.vNormal,Contact0->normal);
669 dVector3Copy(cData.vEp0,Contact0->pos);
670 Contact0->g1 = cData.gCylinder;
671 Contact0->g2 = cData.gBox;
672 dVector3Inv(Contact0->normal);
673 cData.nContacts++;
674
675 if (cData.nContacts != (cData.iFlags & NUMC_MASK))
676 {
677 dContactGeom* Contact1 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
678 Contact1->depth = cData.fDepth1;
679 dVector3Copy(cData.vNormal,Contact1->normal);
680 dVector3Copy(cData.vEp1,Contact1->pos);
681 Contact1->g1 = cData.gCylinder;
682 Contact1->g2 = cData.gBox;
683 dVector3Inv(Contact1->normal);
684 cData.nContacts++;
685 }
686
687 return 1;
688}
689
690
691void _cldClipBoxToCylinder(sCylinderBoxData& cData )
692{
693 dIASSERT(cData.nContacts != (cData.iFlags & NUMC_MASK));
694
695 dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel;
696 // check which circle from cylinder we take for clipping
697 if ( dVector3Dot(cData.vCylinderAxis, cData.vNormal) > REAL(0.0) )
698 {
699 // get top circle
700 vCylinderCirclePos[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
701 vCylinderCirclePos[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
702 vCylinderCirclePos[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
703
704 vCylinderCircleNormal_Rel[0] = REAL(0.0);
705 vCylinderCircleNormal_Rel[1] = REAL(0.0);
706 vCylinderCircleNormal_Rel[2] = REAL(0.0);
707 vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0);
708 }
709 else
710 {
711 // get bottom circle
712 vCylinderCirclePos[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
713 vCylinderCirclePos[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
714 vCylinderCirclePos[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
715
716 vCylinderCircleNormal_Rel[0] = REAL(0.0);
717 vCylinderCircleNormal_Rel[1] = REAL(0.0);
718 vCylinderCircleNormal_Rel[2] = REAL(0.0);
719 vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0);
720 }
721
722 // vNr is normal in Box frame, pointing from Cylinder to Box
723 dVector3 vNr;
724 dMatrix3 mBoxInv;
725
726 // Find a way to use quaternion
727 dMatrix3Inv(cData.mBoxRot,mBoxInv);
728 dMultiplyMat3Vec3(mBoxInv,cData.vNormal,vNr);
729
730 dVector3 vAbsNormal;
731
732 vAbsNormal[0] = dFabs( vNr[0] );
733 vAbsNormal[1] = dFabs( vNr[1] );
734 vAbsNormal[2] = dFabs( vNr[2] );
735
736 // find which face in box is closest to cylinder
737 int iB0, iB1, iB2;
738
739 // Different from Croteam's code
740 if (vAbsNormal[1] > vAbsNormal[0])
741 {
742 // 1 > 0
743 if (vAbsNormal[0]> vAbsNormal[2])
744 {
745 // 0 > 2 -> 1 > 0 >2
746 iB0 = 1; iB1 = 0; iB2 = 2;
747 }
748 else
749 {
750 // 2 > 0-> Must compare 1 and 2
751 if (vAbsNormal[1] > vAbsNormal[2])
752 {
753 // 1 > 2 -> 1 > 2 > 0
754 iB0 = 1; iB1 = 2; iB2 = 0;
755 }
756 else
757 {
758 // 2 > 1 -> 2 > 1 > 0;
759 iB0 = 2; iB1 = 1; iB2 = 0;
760 }
761 }
762 }
763 else
764 {
765 // 0 > 1
766 if (vAbsNormal[1] > vAbsNormal[2])
767 {
768 // 1 > 2 -> 0 > 1 > 2
769 iB0 = 0; iB1 = 1; iB2 = 2;
770 }
771 else
772 {
773 // 2 > 1 -> Must compare 0 and 2
774 if (vAbsNormal[0] > vAbsNormal[2])
775 {
776 // 0 > 2 -> 0 > 2 > 1;
777 iB0 = 0; iB1 = 2; iB2 = 1;
778 }
779 else
780 {
781 // 2 > 0 -> 2 > 0 > 1;
782 iB0 = 2; iB1 = 0; iB2 = 1;
783 }
784 }
785 }
786
787 dVector3 vCenter;
788 // find center of box polygon
789 dVector3 vTemp;
790 if (vNr[iB0] > 0)
791 {
792 dMat3GetCol(cData.mBoxRot,iB0,vTemp);
793 vCenter[0] = cData.vBoxPos[0] - cData.vBoxHalfSize[iB0]*vTemp[0];
794 vCenter[1] = cData.vBoxPos[1] - cData.vBoxHalfSize[iB0]*vTemp[1];
795 vCenter[2] = cData.vBoxPos[2] - cData.vBoxHalfSize[iB0]*vTemp[2];
796 }
797 else
798 {
799 dMat3GetCol(cData.mBoxRot,iB0,vTemp);
800 vCenter[0] = cData.vBoxPos[0] + cData.vBoxHalfSize[iB0]*vTemp[0];
801 vCenter[1] = cData.vBoxPos[1] + cData.vBoxHalfSize[iB0]*vTemp[1];
802 vCenter[2] = cData.vBoxPos[2] + cData.vBoxHalfSize[iB0]*vTemp[2];
803 }
804
805 // find the vertices of box polygon
806 dVector3 avPoints[4];
807 dVector3 avTempArray1[MAX_CYLBOX_CLIP_POINTS];
808 dVector3 avTempArray2[MAX_CYLBOX_CLIP_POINTS];
809
810 int i=0;
811 for(i=0; i<MAX_CYLBOX_CLIP_POINTS; i++)
812 {
813 avTempArray1[i][0] = REAL(0.0);
814 avTempArray1[i][1] = REAL(0.0);
815 avTempArray1[i][2] = REAL(0.0);
816
817 avTempArray2[i][0] = REAL(0.0);
818 avTempArray2[i][1] = REAL(0.0);
819 avTempArray2[i][2] = REAL(0.0);
820 }
821
822 dVector3 vAxis1, vAxis2;
823
824 dMat3GetCol(cData.mBoxRot,iB1,vAxis1);
825 dMat3GetCol(cData.mBoxRot,iB2,vAxis2);
826
827 avPoints[0][0] = vCenter[0] + cData.vBoxHalfSize[iB1] * vAxis1[0] - cData.vBoxHalfSize[iB2] * vAxis2[0];
828 avPoints[0][1] = vCenter[1] + cData.vBoxHalfSize[iB1] * vAxis1[1] - cData.vBoxHalfSize[iB2] * vAxis2[1];
829 avPoints[0][2] = vCenter[2] + cData.vBoxHalfSize[iB1] * vAxis1[2] - cData.vBoxHalfSize[iB2] * vAxis2[2];
830
831 avPoints[1][0] = vCenter[0] - cData.vBoxHalfSize[iB1] * vAxis1[0] - cData.vBoxHalfSize[iB2] * vAxis2[0];
832 avPoints[1][1] = vCenter[1] - cData.vBoxHalfSize[iB1] * vAxis1[1] - cData.vBoxHalfSize[iB2] * vAxis2[1];
833 avPoints[1][2] = vCenter[2] - cData.vBoxHalfSize[iB1] * vAxis1[2] - cData.vBoxHalfSize[iB2] * vAxis2[2];
834
835 avPoints[2][0] = vCenter[0] - cData.vBoxHalfSize[iB1] * vAxis1[0] + cData.vBoxHalfSize[iB2] * vAxis2[0];
836 avPoints[2][1] = vCenter[1] - cData.vBoxHalfSize[iB1] * vAxis1[1] + cData.vBoxHalfSize[iB2] * vAxis2[1];
837 avPoints[2][2] = vCenter[2] - cData.vBoxHalfSize[iB1] * vAxis1[2] + cData.vBoxHalfSize[iB2] * vAxis2[2];
838
839 avPoints[3][0] = vCenter[0] + cData.vBoxHalfSize[iB1] * vAxis1[0] + cData.vBoxHalfSize[iB2] * vAxis2[0];
840 avPoints[3][1] = vCenter[1] + cData.vBoxHalfSize[iB1] * vAxis1[1] + cData.vBoxHalfSize[iB2] * vAxis2[1];
841 avPoints[3][2] = vCenter[2] + cData.vBoxHalfSize[iB1] * vAxis1[2] + cData.vBoxHalfSize[iB2] * vAxis2[2];
842
843 // transform box points to space of cylinder circle
844 dMatrix3 mCylinderInv;
845 dMatrix3Inv(cData.mCylinderRot,mCylinderInv);
846
847 for(i=0; i<4; i++)
848 {
849 dVector3Subtract(avPoints[i],vCylinderCirclePos,vTemp);
850 dMultiplyMat3Vec3(mCylinderInv,vTemp,avPoints[i]);
851 }
852
853 int iTmpCounter1 = 0;
854 int iTmpCounter2 = 0;
855 dVector4 plPlane;
856
857 // plane of cylinder that contains circle for intersection
858 dConstructPlane(vCylinderCircleNormal_Rel,REAL(0.0),plPlane);
859 dClipPolyToPlane(avPoints, 4, avTempArray1, iTmpCounter1, plPlane);
860
861
862 // Body of base circle of Cylinder
863 int nCircleSegment = 0;
864 for (nCircleSegment = 0; nCircleSegment < nCYLINDER_SEGMENT; nCircleSegment++)
865 {
866 dConstructPlane(cData.avCylinderNormals[nCircleSegment],cData.fCylinderRadius,plPlane);
867
868 if (0 == (nCircleSegment % 2))
869 {
870 dClipPolyToPlane( avTempArray1 , iTmpCounter1 , avTempArray2, iTmpCounter2, plPlane);
871 }
872 else
873 {
874 dClipPolyToPlane( avTempArray2, iTmpCounter2, avTempArray1 , iTmpCounter1 , plPlane );
875 }
876
877 dIASSERT( iTmpCounter1 >= 0 && iTmpCounter1 <= MAX_CYLBOX_CLIP_POINTS );
878 dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= MAX_CYLBOX_CLIP_POINTS );
879 }
880
881 // back transform clipped points to absolute space
882 dReal ftmpdot;
883 dReal fTempDepth;
884 dVector3 vPoint;
885
886 if (nCircleSegment % 2)
887 {
888 for( i=0; i<iTmpCounter2; i++)
889 {
890 dMULTIPLY0_331(vPoint,cData.mCylinderRot,avTempArray2[i]);
891 vPoint[0] += vCylinderCirclePos[0];
892 vPoint[1] += vCylinderCirclePos[1];
893 vPoint[2] += vCylinderCirclePos[2];
894
895 dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
896 ftmpdot = dVector3Dot(vTemp, cData.vNormal);
897 fTempDepth = cData.fBestrc - ftmpdot;
898 // Depth must be positive
899 if (fTempDepth > REAL(0.0))
900 {
901 // generate contacts
902 dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
903 Contact0->depth = fTempDepth;
904 dVector3Copy(cData.vNormal,Contact0->normal);
905 dVector3Copy(vPoint,Contact0->pos);
906 Contact0->g1 = cData.gCylinder;
907 Contact0->g2 = cData.gBox;
908 dVector3Inv(Contact0->normal);
909 cData.nContacts++;
910
911 if (cData.nContacts == (cData.iFlags & NUMC_MASK))
912 {
913 break;
914 }
915 }
916 }
917 }
918 else
919 {
920 for( i=0; i<iTmpCounter1; i++)
921 {
922 dMULTIPLY0_331(vPoint,cData.mCylinderRot,avTempArray1[i]);
923 vPoint[0] += vCylinderCirclePos[0];
924 vPoint[1] += vCylinderCirclePos[1];
925 vPoint[2] += vCylinderCirclePos[2];
926
927 dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
928 ftmpdot = dVector3Dot(vTemp, cData.vNormal);
929 fTempDepth = cData.fBestrc - ftmpdot;
930 // Depth must be positive
931 if (fTempDepth > REAL(0.0))
932 {
933 // generate contacts
934 dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
935 Contact0->depth = fTempDepth;
936 dVector3Copy(cData.vNormal,Contact0->normal);
937 dVector3Copy(vPoint,Contact0->pos);
938 Contact0->g1 = cData.gCylinder;
939 Contact0->g2 = cData.gBox;
940 dVector3Inv(Contact0->normal);
941 cData.nContacts++;
942
943 if (cData.nContacts == (cData.iFlags & NUMC_MASK))
944 {
945 break;
946 }
947 }
948 }
949 }
950}
951
952
953// Cylinder - Box by CroTeam
954// Ported by Nguyen Binh
955int dCollideCylinderBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
956{
957 dIASSERT (skip >= (int)sizeof(dContactGeom));
958 dIASSERT (o1->type == dCylinderClass);
959 dIASSERT (o2->type == dBoxClass);
960 dIASSERT ((flags & NUMC_MASK) >= 1);
961
962 sCylinderBoxData cData;
963
964 // Assign ODE stuff
965 cData.gCylinder = o1;
966 cData.gBox = o2;
967 cData.iFlags = flags;
968 cData.iSkip = skip;
969 cData.gContact = contact;
970
971 // initialize collider
972 _cldInitCylinderBox( cData );
973
974 // do intersection test and find best separating axis
975 if(!_cldTestSeparatingAxes( cData ) )
976 {
977 // if not found do nothing
978 return 0;
979 }
980
981 // if best separation axis is not found
982 if ( cData.iBestAxis == 0 )
983 {
984 // this should not happen (we should already exit in that case)
985 dIASSERT(0);
986 // do nothing
987 return 0;
988 }
989
990 dReal fdot = dVector3Dot(cData.vNormal,cData.vCylinderAxis);
991 // choose which clipping method are we going to apply
992 if (dFabs(fdot) < REAL(0.9) )
993 {
994 // clip cylinder over box
995 if(!_cldClipCylinderToBox(cData))
996 {
997 return 0;
998 }
999 }
1000 else
1001 {
1002 _cldClipBoxToCylinder(cData);
1003 }
1004
1005 return cData.nContacts;
1006}
1007
diff --git a/libraries/ode-0.9/ode/src/collision_cylinder_plane.cpp b/libraries/ode-0.9/ode/src/collision_cylinder_plane.cpp
deleted file mode 100644
index f85701d..0000000
--- a/libraries/ode-0.9/ode/src/collision_cylinder_plane.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
1/*************************************************************************
2* *
3* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4* All rights reserved. Email: russ@q12.org Web: www.q12.org *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of EITHER: *
8* (1) The GNU Lesser General Public License as published by the Free *
9* Software Foundation; either version 2.1 of the License, or (at *
10* your option) any later version. The text of the GNU Lesser *
11* General Public License is included with this library in the *
12* file LICENSE.TXT. *
13* (2) The BSD-style license that is included with this library in *
14* the file LICENSE-BSD.TXT. *
15* *
16* This library is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20* *
21*************************************************************************/
22
23
24/*
25 * Cylinder-Plane collider by Christoph Beyer ( boernerb@web.de )
26 *
27 * This testing basically comes down to testing the intersection
28 * of the cylinder caps (discs) with the plane.
29 *
30 */
31
32#include <ode/collision.h>
33#include <ode/matrix.h>
34#include <ode/rotation.h>
35#include <ode/odemath.h>
36#include <ode/objects.h>
37
38#include "collision_kernel.h" // for dxGeom
39#include "collision_util.h"
40
41
42int dCollideCylinderPlane(dxGeom *Cylinder, dxGeom *Plane, int flags, dContactGeom *contact, int skip)
43{
44 dIASSERT (skip >= (int)sizeof(dContactGeom));
45 dIASSERT (Cylinder->type == dCylinderClass);
46 dIASSERT (Plane->type == dPlaneClass);
47 dIASSERT ((flags & NUMC_MASK) >= 1);
48
49 int GeomCount = 0; // count of used contactgeoms
50
51#ifdef dSINGLE
52 const dReal toleranz = REAL(0.0001);
53#endif
54#ifdef dDOUBLE
55 const dReal toleranz = REAL(0.0000001);
56#endif
57
58 // Get the properties of the cylinder (length+radius)
59 dReal radius, length;
60 dGeomCylinderGetParams(Cylinder, &radius, &length);
61 dVector3 &cylpos = Cylinder->final_posr->pos;
62 // and the plane
63 dVector4 planevec;
64 dGeomPlaneGetParams(Plane, planevec);
65 dVector3 PlaneNormal = {planevec[0],planevec[1],planevec[2]};
66 dVector3 PlanePos = {planevec[0] * planevec[3],planevec[1] * planevec[3],planevec[2] * planevec[3]};
67
68 dVector3 G1Pos1, G1Pos2, vDir1;
69 vDir1[0] = Cylinder->final_posr->R[2];
70 vDir1[1] = Cylinder->final_posr->R[6];
71 vDir1[2] = Cylinder->final_posr->R[10];
72
73 dReal s;
74 s = length * REAL(0.5);
75 G1Pos2[0] = vDir1[0] * s + cylpos[0];
76 G1Pos2[1] = vDir1[1] * s + cylpos[1];
77 G1Pos2[2] = vDir1[2] * s + cylpos[2];
78
79 G1Pos1[0] = vDir1[0] * -s + cylpos[0];
80 G1Pos1[1] = vDir1[1] * -s + cylpos[1];
81 G1Pos1[2] = vDir1[2] * -s + cylpos[2];
82
83 dVector3 C;
84
85 // parallel-check
86 s = vDir1[0] * PlaneNormal[0] + vDir1[1] * PlaneNormal[1] + vDir1[2] * PlaneNormal[2];
87 if(s < 0)
88 s += REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel
89 else
90 s -= REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel
91 if(s < toleranz && s > (-toleranz))
92 {
93 // discs are parallel to the plane
94
95 // 1.compute if, and where contacts are
96 dVector3 P;
97 s = planevec[3] - dVector3Dot(planevec, G1Pos1);
98 dReal t;
99 t = planevec[3] - dVector3Dot(planevec, G1Pos2);
100 if(s >= t) // s == t does never happen,
101 {
102 if(s >= 0)
103 {
104 // 1. Disc
105 dVector3Copy(G1Pos1, P);
106 }
107 else
108 return GeomCount; // no contacts
109 }
110 else
111 {
112 if(t >= 0)
113 {
114 // 2. Disc
115 dVector3Copy(G1Pos2, P);
116 }
117 else
118 return GeomCount; // no contacts
119 }
120
121 // 2. generate a coordinate-system on the disc
122 dVector3 V1, V2;
123 if(vDir1[0] < toleranz && vDir1[0] > (-toleranz))
124 {
125 // not x-axis
126 V1[0] = vDir1[0] + REAL(1.0); // random value
127 V1[1] = vDir1[1];
128 V1[2] = vDir1[2];
129 }
130 else
131 {
132 // maybe x-axis
133 V1[0] = vDir1[0];
134 V1[1] = vDir1[1] + REAL(1.0); // random value
135 V1[2] = vDir1[2];
136 }
137 // V1 is now another direction than vDir1
138 // Cross-product
139 dVector3Cross(V1, vDir1, V2);
140 // make unit V2
141 t = dVector3Length(V2);
142 t = radius / t;
143 dVector3Scale(V2, t);
144 // cross again
145 dVector3Cross(V2, vDir1, V1);
146 // |V2| is 'radius' and vDir1 unit, so |V1| is 'radius'
147 // V1 = first axis
148 // V2 = second axis
149
150 // 3. generate contactpoints
151
152 // Potential contact 1
153 dVector3Add(P, V1, contact->pos);
154 contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
155 if(contact->depth > 0)
156 {
157 dVector3Copy(PlaneNormal, contact->normal);
158 contact->g1 = Cylinder;
159 contact->g2 = Plane;
160 GeomCount++;
161 if( GeomCount >= (flags & NUMC_MASK))
162 return GeomCount; // enough contactgeoms
163 contact = (dContactGeom *)((char *)contact + skip);
164 }
165
166 // Potential contact 2
167 dVector3Subtract(P, V1, contact->pos);
168 contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
169 if(contact->depth > 0)
170 {
171 dVector3Copy(PlaneNormal, contact->normal);
172 contact->g1 = Cylinder;
173 contact->g2 = Plane;
174 GeomCount++;
175 if( GeomCount >= (flags & NUMC_MASK))
176 return GeomCount; // enough contactgeoms
177 contact = (dContactGeom *)((char *)contact + skip);
178 }
179
180 // Potential contact 3
181 dVector3Add(P, V2, contact->pos);
182 contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
183 if(contact->depth > 0)
184 {
185 dVector3Copy(PlaneNormal, contact->normal);
186 contact->g1 = Cylinder;
187 contact->g2 = Plane;
188 GeomCount++;
189 if( GeomCount >= (flags & NUMC_MASK))
190 return GeomCount; // enough contactgeoms
191 contact = (dContactGeom *)((char *)contact + skip);
192 }
193
194 // Potential contact 4
195 dVector3Subtract(P, V2, contact->pos);
196 contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
197 if(contact->depth > 0)
198 {
199 dVector3Copy(PlaneNormal, contact->normal);
200 contact->g1 = Cylinder;
201 contact->g2 = Plane;
202 GeomCount++;
203 if( GeomCount >= (flags & NUMC_MASK))
204 return GeomCount; // enough contactgeoms
205 contact = (dContactGeom *)((char *)contact + skip);
206 }
207 }
208 else
209 {
210 dReal t = dVector3Dot(PlaneNormal, vDir1);
211 C[0] = vDir1[0] * t - PlaneNormal[0];
212 C[1] = vDir1[1] * t - PlaneNormal[1];
213 C[2] = vDir1[2] * t - PlaneNormal[2];
214 s = dVector3Length(C);
215 // move C onto the circle
216 s = radius / s;
217 dVector3Scale(C, s);
218
219 // deepest point of disc 1
220 dVector3Add(C, G1Pos1, contact->pos);
221
222 // depth of the deepest point
223 contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
224 if(contact->depth >= 0)
225 {
226 dVector3Copy(PlaneNormal, contact->normal);
227 contact->g1 = Cylinder;
228 contact->g2 = Plane;
229 GeomCount++;
230 if( GeomCount >= (flags & NUMC_MASK))
231 return GeomCount; // enough contactgeoms
232 contact = (dContactGeom *)((char *)contact + skip);
233 }
234
235 // C is still computed
236
237 // deepest point of disc 2
238 dVector3Add(C, G1Pos2, contact->pos);
239
240 // depth of the deepest point
241 contact->depth = planevec[3] - planevec[0] * contact->pos[0] - planevec[1] * contact->pos[1] - planevec[2] * contact->pos[2];
242 if(contact->depth >= 0)
243 {
244 dVector3Copy(PlaneNormal, contact->normal);
245 contact->g1 = Cylinder;
246 contact->g2 = Plane;
247 GeomCount++;
248 if( GeomCount >= (flags & NUMC_MASK))
249 return GeomCount; // enough contactgeoms
250 contact = (dContactGeom *)((char *)contact + skip);
251 }
252 }
253 return GeomCount;
254}
diff --git a/libraries/ode-0.9/ode/src/collision_cylinder_sphere.cpp b/libraries/ode-0.9/ode/src/collision_cylinder_sphere.cpp
deleted file mode 100644
index 964c531..0000000
--- a/libraries/ode-0.9/ode/src/collision_cylinder_sphere.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
1/*************************************************************************
2* *
3* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4* All rights reserved. Email: russ@q12.org Web: www.q12.org *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of EITHER: *
8* (1) The GNU Lesser General Public License as published by the Free *
9* Software Foundation; either version 2.1 of the License, or (at *
10* your option) any later version. The text of the GNU Lesser *
11* General Public License is included with this library in the *
12* file LICENSE.TXT. *
13* (2) The BSD-style license that is included with this library in *
14* the file LICENSE-BSD.TXT. *
15* *
16* This library is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20* *
21*************************************************************************/
22
23
24/*******************************************************************
25 * *
26 * cylinder-sphere collider by Christoph Beyer (boernerb@web.de) *
27 * *
28 * In Cylinder/Sphere-collisions, there are three possibilies: *
29 * 1. collision with the cylinder's nappe *
30 * 2. collision with one of the cylinder's disc *
31 * 3. collision with one of the disc's border *
32 * *
33 * This collider computes two distances (s, t) and based on them, *
34 * it decides, which collision we have. *
35 * This collider always generates 1 (or 0, if we have no collison) *
36 * contacts. *
37 * It is able to "separate" cylinder and sphere in all *
38 * configurations, but it never pays attention to velocity. *
39 * So, in extrem situations, "tunneling-effect" is possible. *
40 * *
41 *******************************************************************/
42
43#include <ode/collision.h>
44#include <ode/matrix.h>
45#include <ode/rotation.h>
46#include <ode/odemath.h>
47#include <ode/objects.h>
48#include "collision_kernel.h" // for dxGeom
49#include "collision_util.h"
50
51int dCollideCylinderSphere(dxGeom* Cylinder, dxGeom* Sphere,
52 int flags, dContactGeom *contact, int skip)
53{
54 dIASSERT (skip >= (int)sizeof(dContactGeom));
55 dIASSERT (Cylinder->type == dCylinderClass);
56 dIASSERT (Sphere->type == dSphereClass);
57 dIASSERT ((flags & NUMC_MASK) >= 1);
58
59 unsigned char* pContactData = (unsigned char*)contact;
60 int GeomCount = 0; // count of used contacts
61
62#ifdef dSINGLE
63 const dReal toleranz = REAL(0.0001);
64#endif
65#ifdef dDOUBLE
66 const dReal toleranz = REAL(0.0000001);
67#endif
68
69 // get the data from the geoms
70 dReal radius, length;
71 dGeomCylinderGetParams(Cylinder, &radius, &length);
72 dVector3 &cylpos = Cylinder->final_posr->pos;
73 const dReal* pfRot1 = dGeomGetRotation(Cylinder);
74
75 dReal radius2;
76 radius2 = dGeomSphereGetRadius(Sphere);
77 const dReal* SpherePos = dGeomGetPosition(Sphere);
78
79 // G1Pos1 is the middle of the first disc
80 // G1Pos2 is the middle of the second disc
81 // vDir1 is the unit direction of the cylinderaxis
82 dVector3 G1Pos1, G1Pos2, vDir1;
83 vDir1[0] = Cylinder->final_posr->R[2];
84 vDir1[1] = Cylinder->final_posr->R[6];
85 vDir1[2] = Cylinder->final_posr->R[10];
86
87 dReal s;
88 s = length * REAL(0.5); // just a precomputed factor
89 G1Pos2[0] = vDir1[0] * s + cylpos[0];
90 G1Pos2[1] = vDir1[1] * s + cylpos[1];
91 G1Pos2[2] = vDir1[2] * s + cylpos[2];
92
93 G1Pos1[0] = vDir1[0] * -s + cylpos[0];
94 G1Pos1[1] = vDir1[1] * -s + cylpos[1];
95 G1Pos1[2] = vDir1[2] * -s + cylpos[2];
96
97 dVector3 C;
98 dReal t;
99 // Step 1: compute the two distances 's' and 't'
100 // 's' is the distance from the first disc (in vDir1-/Zylinderaxis-direction), the disc with G1Pos1 in the middle
101 s = (SpherePos[0] - G1Pos1[0]) * vDir1[0] - (G1Pos1[1] - SpherePos[1]) * vDir1[1] - (G1Pos1[2] - SpherePos[2]) * vDir1[2];
102 if(s < (-radius2) || s > (length + radius2) )
103 {
104 // Sphere is too far away from the discs
105 // no collision
106 return 0;
107 }
108
109 // C is the direction from Sphere-middle to the cylinder-axis (vDir1); C is orthogonal to the cylinder-axis
110 C[0] = s * vDir1[0] + G1Pos1[0] - SpherePos[0];
111 C[1] = s * vDir1[1] + G1Pos1[1] - SpherePos[1];
112 C[2] = s * vDir1[2] + G1Pos1[2] - SpherePos[2];
113 // t is the distance from the Sphere-middle to the cylinder-axis!
114 t = dVector3Length(C);
115 if(t > (radius + radius2) )
116 {
117 // Sphere is too far away from the cylinder axis!
118 // no collision
119 return 0;
120 }
121
122 // decide which kind of collision we have:
123 if(t > radius && (s < 0 || s > length) )
124 {
125 // 3. collision
126 if(s <= 0)
127 {
128 contact->depth = radius2 - dSqrt( (s) * (s) + (t - radius) * (t - radius) );
129 if(contact->depth < 0)
130 {
131 // no collision!
132 return 0;
133 }
134 contact->pos[0] = C[0] / t * -radius + G1Pos1[0];
135 contact->pos[1] = C[1] / t * -radius + G1Pos1[1];
136 contact->pos[2] = C[2] / t * -radius + G1Pos1[2];
137 contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
138 contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
139 contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
140 contact->g1 = Cylinder;
141 contact->g2 = Sphere;
142 GeomCount++;
143 return GeomCount;
144 }
145 else
146 {
147 // now s is bigger than length here!
148 contact->depth = radius2 - dSqrt( (s - length) * (s - length) + (t - radius) * (t - radius) );
149 if(contact->depth < 0)
150 {
151 // no collision!
152 return 0;
153 }
154 contact->pos[0] = C[0] / t * -radius + G1Pos2[0];
155 contact->pos[1] = C[1] / t * -radius + G1Pos2[1];
156 contact->pos[2] = C[2] / t * -radius + G1Pos2[2];
157 contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
158 contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
159 contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
160 contact->g1 = Cylinder;
161 contact->g2 = Sphere;
162 GeomCount++;
163 return GeomCount;
164 }
165 }
166 else if( (radius - t) <= s && (radius - t) <= (length - s) )
167 {
168 // 1. collsision
169 if(t > (radius2 + toleranz))
170 {
171 // cylinder-axis is outside the sphere
172 contact->depth = (radius2 + radius) - t;
173 if(contact->depth < 0)
174 {
175 // should never happen, but just for safeness
176 return 0;
177 }
178 else
179 {
180 C[0] /= t;
181 C[1] /= t;
182 C[2] /= t;
183 contact->pos[0] = C[0] * radius2 + SpherePos[0];
184 contact->pos[1] = C[1] * radius2 + SpherePos[1];
185 contact->pos[2] = C[2] * radius2 + SpherePos[2];
186 contact->normal[0] = C[0];
187 contact->normal[1] = C[1];
188 contact->normal[2] = C[2];
189 contact->g1 = Cylinder;
190 contact->g2 = Sphere;
191 GeomCount++;
192 return GeomCount;
193 }
194 }
195 else
196 {
197 // cylinder-axis is outside of the sphere
198 contact->depth = (radius2 + radius) - t;
199 if(contact->depth < 0)
200 {
201 // should never happen, but just for safeness
202 return 0;
203 }
204 else
205 {
206 contact->pos[0] = C[0] + SpherePos[0];
207 contact->pos[1] = C[1] + SpherePos[1];
208 contact->pos[2] = C[2] + SpherePos[2];
209 contact->normal[0] = C[0] / t;
210 contact->normal[1] = C[1] / t;
211 contact->normal[2] = C[2] / t;
212 contact->g1 = Cylinder;
213 contact->g2 = Sphere;
214 GeomCount++;
215 return GeomCount;
216 }
217 }
218 }
219 else
220 {
221 // 2. collision
222 if(s <= (length * REAL(0.5)) )
223 {
224 // collsision with the first disc
225 contact->depth = s + radius2;
226 if(contact->depth < 0)
227 {
228 // should never happen, but just for safeness
229 return 0;
230 }
231 contact->pos[0] = radius2 * vDir1[0] + SpherePos[0];
232 contact->pos[1] = radius2 * vDir1[1] + SpherePos[1];
233 contact->pos[2] = radius2 * vDir1[2] + SpherePos[2];
234 contact->normal[0] = vDir1[0];
235 contact->normal[1] = vDir1[1];
236 contact->normal[2] = vDir1[2];
237 contact->g1 = Cylinder;
238 contact->g2 = Sphere;
239 GeomCount++;
240 return GeomCount;
241 }
242 else
243 {
244 // collsision with the second disc
245 contact->depth = (radius2 + length - s);
246 if(contact->depth < 0)
247 {
248 // should never happen, but just for safeness
249 return 0;
250 }
251 contact->pos[0] = radius2 * -vDir1[0] + SpherePos[0];
252 contact->pos[1] = radius2 * -vDir1[1] + SpherePos[1];
253 contact->pos[2] = radius2 * -vDir1[2] + SpherePos[2];
254 contact->normal[0] = -vDir1[0];
255 contact->normal[1] = -vDir1[1];
256 contact->normal[2] = -vDir1[2];
257 contact->g1 = Cylinder;
258 contact->g2 = Sphere;
259 GeomCount++;
260 return GeomCount;
261 }
262 }
263 return GeomCount;
264}
diff --git a/libraries/ode-0.9/ode/src/collision_cylinder_trimesh.cpp b/libraries/ode-0.9/ode/src/collision_cylinder_trimesh.cpp
deleted file mode 100644
index 342be04..0000000
--- a/libraries/ode-0.9/ode/src/collision_cylinder_trimesh.cpp
+++ /dev/null
@@ -1,1145 +0,0 @@
1/*************************************************************************
2* *
3* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4* All rights reserved. Email: russ@q12.org Web: www.q12.org *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of EITHER: *
8* (1) The GNU Lesser General Public License as published by the Free *
9* Software Foundation; either version 2.1 of the License, or (at *
10* your option) any later version. The text of the GNU Lesser *
11* General Public License is included with this library in the *
12* file LICENSE.TXT. *
13* (2) The BSD-style license that is included with this library in *
14* the file LICENSE-BSD.TXT. *
15* *
16* This library is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20* *
21*************************************************************************/
22
23/*
24 * Cylinder-trimesh collider by Alen Ladavac
25 * Ported to ODE by Nguyen Binh
26 */
27
28
29#include <ode/collision.h>
30#include <ode/matrix.h>
31#include <ode/rotation.h>
32#include <ode/odemath.h>
33#include "collision_util.h"
34
35#define TRIMESH_INTERNAL
36#include "collision_trimesh_internal.h"
37
38#define MAX_REAL dInfinity
39static const int nCYLINDER_AXIS = 2;
40static const int nCYLINDER_CIRCLE_SEGMENTS = 8;
41static const int nMAX_CYLINDER_TRIANGLE_CLIP_POINTS = 12;
42
43#define OPTIMIZE_CONTACTS 1
44
45// Local contacts data
46typedef struct _sLocalContactData
47{
48 dVector3 vPos;
49 dVector3 vNormal;
50 dReal fDepth;
51 int triIndex;
52 int nFlags; // 0 = filtered out, 1 = OK
53}sLocalContactData;
54
55typedef struct _sCylinderTrimeshColliderData
56{
57 // cylinder data
58 dMatrix3 mCylinderRot;
59 dQuaternion qCylinderRot;
60 dQuaternion qInvCylinderRot;
61 dVector3 vCylinderPos;
62 dVector3 vCylinderAxis;
63 dReal fCylinderRadius;
64 dReal fCylinderSize;
65 dVector3 avCylinderNormals[nCYLINDER_CIRCLE_SEGMENTS];
66
67 // mesh data
68 dQuaternion qTrimeshRot;
69 dQuaternion qInvTrimeshRot;
70 dMatrix3 mTrimeshRot;
71 dVector3 vTrimeshPos;
72
73 // global collider data
74 dVector3 vBestPoint;
75 dReal fBestDepth;
76 dReal fBestCenter;
77 dReal fBestrt;
78 int iBestAxis;
79 dVector3 vContactNormal;
80 dVector3 vNormal;
81 dVector3 vE0;
82 dVector3 vE1;
83 dVector3 vE2;
84
85 // ODE stuff
86 dGeomID gCylinder;
87 dxTriMesh* gTrimesh;
88 dContactGeom* gContact;
89 int iFlags;
90 int iSkip;
91 int nContacts;// = 0;
92 sLocalContactData* gLocalContacts;
93} sCylinderTrimeshColliderData;
94
95// Short type name
96typedef sCylinderTrimeshColliderData sData;
97
98// Use to classify contacts to be "near" in position
99static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4
100// Use to classify contacts to be "near" in normal direction
101static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4
102
103// If this two contact can be classified as "near"
104inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2)
105{
106 int bPosNear = 0;
107 int bSameDir = 0;
108 dVector3 vDiff;
109
110 // First check if they are "near" in position
111 dVector3Subtract(c1.vPos,c2.vPos,vDiff);
112 if ( (dFabs(vDiff[0]) < fSameContactPositionEpsilon)
113 &&(dFabs(vDiff[1]) < fSameContactPositionEpsilon)
114 &&(dFabs(vDiff[2]) < fSameContactPositionEpsilon))
115 {
116 bPosNear = 1;
117 }
118
119 // Second check if they are "near" in normal direction
120 dVector3Subtract(c1.vNormal,c2.vNormal,vDiff);
121 if ( (dFabs(vDiff[0]) < fSameContactNormalEpsilon)
122 &&(dFabs(vDiff[1]) < fSameContactNormalEpsilon)
123 &&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) )
124 {
125 bSameDir = 1;
126 }
127
128 // Will be "near" if position and normal direction are "near"
129 return (bPosNear && bSameDir);
130}
131
132inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2)
133{
134 // The not better will be throw away
135 // You can change the selection criteria here
136 return (c1.fDepth > c2.fDepth);
137}
138
139// iterate through gLocalContacts and filtered out "near contact"
140inline void _OptimizeLocalContacts(sData& cData)
141{
142 int nContacts = cData.nContacts;
143
144 for (int i = 0; i < nContacts-1; i++)
145 {
146 for (int j = i+1; j < nContacts; j++)
147 {
148 if (_IsNearContacts(cData.gLocalContacts[i],cData.gLocalContacts[j]))
149 {
150 // If they are seem to be the same then filtered
151 // out the least penetrate one
152 if (_IsBetter(cData.gLocalContacts[j],cData.gLocalContacts[i]))
153 {
154 cData.gLocalContacts[i].nFlags = 0; // filtered 1st contact
155 }
156 else
157 {
158 cData.gLocalContacts[j].nFlags = 0; // filtered 2nd contact
159 }
160
161 // NOTE
162 // There is other way is to add two depth together but
163 // it not work so well. Why???
164 }
165 }
166 }
167}
168
169inline int _ProcessLocalContacts(sData& cData)
170{
171 if (cData.nContacts == 0)
172 {
173 return 0;
174 }
175
176#ifdef OPTIMIZE_CONTACTS
177 if (cData.nContacts > 1 && !(cData.iFlags & CONTACTS_UNIMPORTANT))
178 {
179 // Can be optimized...
180 _OptimizeLocalContacts(cData);
181 }
182#endif
183
184 int iContact = 0;
185 dContactGeom* Contact = 0;
186
187 int nFinalContact = 0;
188
189 for (iContact = 0; iContact < cData.nContacts; iContact ++)
190 {
191 if (1 == cData.gLocalContacts[iContact].nFlags)
192 {
193 Contact = SAFECONTACT(cData.iFlags, cData.gContact, nFinalContact, cData.iSkip);
194 Contact->depth = cData.gLocalContacts[iContact].fDepth;
195 dVector3Copy(cData.gLocalContacts[iContact].vNormal,Contact->normal);
196 dVector3Copy(cData.gLocalContacts[iContact].vPos,Contact->pos);
197 Contact->g1 = cData.gCylinder;
198 Contact->g2 = cData.gTrimesh;
199 Contact->side2 = cData.gLocalContacts[iContact].triIndex;
200 dVector3Inv(Contact->normal);
201
202 nFinalContact++;
203 }
204 }
205 // debug
206 //if (nFinalContact != cData.nContacts)
207 //{
208 // printf("[Info] %d contacts generated,%d filtered.\n",cData.nContacts,cData.nContacts-nFinalContact);
209 //}
210
211 return nFinalContact;
212}
213
214
215bool _cldTestAxis(sData& cData,
216 const dVector3 &v0,
217 const dVector3 &v1,
218 const dVector3 &v2,
219 dVector3& vAxis,
220 int iAxis,
221 bool bNoFlip = false)
222{
223
224 // calculate length of separating axis vector
225 dReal fL = dVector3Length(vAxis);
226 // if not long enough
227 if ( fL < REAL(1e-5) )
228 {
229 // do nothing
230 return true;
231 }
232
233 // otherwise normalize it
234 vAxis[0] /= fL;
235 vAxis[1] /= fL;
236 vAxis[2] /= fL;
237
238 dReal fdot1 = dVector3Dot(cData.vCylinderAxis,vAxis);
239 // project capsule on vAxis
240 dReal frc;
241
242 if (dFabs(fdot1) > REAL(1.0) )
243 {
244// fdot1 = REAL(1.0);
245 frc = dFabs(cData.fCylinderSize* REAL(0.5));
246 }
247 else
248 {
249 frc = dFabs((cData.fCylinderSize* REAL(0.5)) * fdot1)
250 + cData.fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1));
251 }
252
253 dVector3 vV0;
254 dVector3Subtract(v0,cData.vCylinderPos,vV0);
255 dVector3 vV1;
256 dVector3Subtract(v1,cData.vCylinderPos,vV1);
257 dVector3 vV2;
258 dVector3Subtract(v2,cData.vCylinderPos,vV2);
259
260 // project triangle on vAxis
261 dReal afv[3];
262 afv[0] = dVector3Dot( vV0 , vAxis );
263 afv[1] = dVector3Dot( vV1 , vAxis );
264 afv[2] = dVector3Dot( vV2 , vAxis );
265
266 dReal fMin = MAX_REAL;
267 dReal fMax = -MAX_REAL;
268
269 // for each vertex
270 for(int i = 0; i < 3; i++)
271 {
272 // find minimum
273 if (afv[i]<fMin)
274 {
275 fMin = afv[i];
276 }
277 // find maximum
278 if (afv[i]>fMax)
279 {
280 fMax = afv[i];
281 }
282 }
283
284 // find capsule's center of interval on axis
285 dReal fCenter = (fMin+fMax)* REAL(0.5);
286 // calculate triangles halfinterval
287 dReal fTriangleRadius = (fMax-fMin)*REAL(0.5);
288
289 // if they do not overlap,
290 if( dFabs(fCenter) > (frc+fTriangleRadius) )
291 {
292 // exit, we have no intersection
293 return false;
294 }
295
296 // calculate depth
297 dReal fDepth = -(dFabs(fCenter) - (frc + fTriangleRadius ) );
298
299 // if greater then best found so far
300 if ( fDepth < cData.fBestDepth )
301 {
302 // remember depth
303 cData.fBestDepth = fDepth;
304 cData.fBestCenter = fCenter;
305 cData.fBestrt = frc;
306 dVector3Copy(vAxis,cData.vContactNormal);
307 cData.iBestAxis = iAxis;
308
309 // flip normal if interval is wrong faced
310 if ( fCenter< REAL(0.0) && !bNoFlip)
311 {
312 dVector3Inv(cData.vContactNormal);
313 cData.fBestCenter = -fCenter;
314 }
315 }
316
317 return true;
318}
319
320// intersection test between edge and circle
321bool _cldTestCircleToEdgeAxis(sData& cData,
322 const dVector3 &v0, const dVector3 &v1, const dVector3 &v2,
323 const dVector3 &vCenterPoint, const dVector3 &vCylinderAxis1,
324 const dVector3 &vVx0, const dVector3 &vVx1, int iAxis)
325{
326 // calculate direction of edge
327 dVector3 vkl;
328 dVector3Subtract( vVx1 , vVx0 , vkl);
329 dNormalize3(vkl);
330 // starting point of edge
331 dVector3 vol;
332 dVector3Copy(vVx0,vol);
333
334 // calculate angle cosine between cylinder axis and edge
335 dReal fdot2 = dVector3Dot(vkl , vCylinderAxis1);
336
337 // if edge is perpendicular to cylinder axis
338 if(dFabs(fdot2)<REAL(1e-5))
339 {
340 // this can't be separating axis, because edge is parallel to circle plane
341 return true;
342 }
343
344 // find point of intersection between edge line and circle plane
345 dVector3 vTemp;
346 dVector3Subtract(vCenterPoint,vol,vTemp);
347 dReal fdot1 = dVector3Dot(vTemp,vCylinderAxis1);
348 dVector3 vpnt;// = vol + vkl * (fdot1/fdot2);
349 vpnt[0] = vol[0] + vkl[0] * fdot1/fdot2;
350 vpnt[1] = vol[1] + vkl[1] * fdot1/fdot2;
351 vpnt[2] = vol[2] + vkl[2] * fdot1/fdot2;
352
353 // find tangent vector on circle with same center (vCenterPoint) that touches point of intersection (vpnt)
354 dVector3 vTangent;
355 dVector3Subtract(vCenterPoint,vpnt,vTemp);
356 dVector3Cross(vTemp,vCylinderAxis1,vTangent);
357
358 // find vector orthogonal both to tangent and edge direction
359 dVector3 vAxis;
360 dVector3Cross(vTangent,vkl,vAxis);
361
362 // use that vector as separating axis
363 return _cldTestAxis( cData ,v0, v1, v2, vAxis, iAxis );
364}
365
366// helper for less key strokes
367// r = ( (v1 - v2) cross v3 ) cross v3
368inline void _CalculateAxis(const dVector3& v1,
369 const dVector3& v2,
370 const dVector3& v3,
371 dVector3& r)
372{
373 dVector3 t1;
374 dVector3 t2;
375
376 dVector3Subtract(v1,v2,t1);
377 dVector3Cross(t1,v3,t2);
378 dVector3Cross(t2,v3,r);
379}
380
381bool _cldTestSeparatingAxes(sData& cData,
382 const dVector3 &v0,
383 const dVector3 &v1,
384 const dVector3 &v2)
385{
386
387 // calculate edge vectors
388 dVector3Subtract(v1 ,v0 , cData.vE0);
389 // cData.vE1 has been calculated before -> so save some cycles here
390 dVector3Subtract(v0 ,v2 , cData.vE2);
391
392 // calculate caps centers in absolute space
393 dVector3 vCp0;
394 vCp0[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize* REAL(0.5));
395 vCp0[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize* REAL(0.5));
396 vCp0[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize* REAL(0.5));
397
398 dVector3 vCp1;
399 vCp1[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize* REAL(0.5));
400 vCp1[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize* REAL(0.5));
401 vCp1[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize* REAL(0.5));
402
403 // reset best axis
404 cData.iBestAxis = 0;
405 dVector3 vAxis;
406
407 // axis cData.vNormal
408 //vAxis = -cData.vNormal;
409 vAxis[0] = -cData.vNormal[0];
410 vAxis[1] = -cData.vNormal[1];
411 vAxis[2] = -cData.vNormal[2];
412 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 1, true))
413 {
414 return false;
415 }
416
417 // axis CxE0
418 // vAxis = ( cData.vCylinderAxis cross cData.vE0 );
419 dVector3Cross(cData.vCylinderAxis, cData.vE0,vAxis);
420 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 2))
421 {
422 return false;
423 }
424
425 // axis CxE1
426 // vAxis = ( cData.vCylinderAxis cross cData.vE1 );
427 dVector3Cross(cData.vCylinderAxis, cData.vE1,vAxis);
428 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 3))
429 {
430 return false;
431 }
432
433 // axis CxE2
434 // vAxis = ( cData.vCylinderAxis cross cData.vE2 );
435 dVector3Cross(cData.vCylinderAxis, cData.vE2,vAxis);
436 if (!_cldTestAxis( cData ,v0, v1, v2, vAxis, 4))
437 {
438 return false;
439 }
440
441 // first vertex on triangle
442 // axis ((V0-Cp0) x C) x C
443 //vAxis = ( ( v0-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
444 _CalculateAxis(v0 , vCp0 , cData.vCylinderAxis , vAxis);
445 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 11))
446 {
447 return false;
448 }
449
450 // second vertex on triangle
451 // axis ((V1-Cp0) x C) x C
452 // vAxis = ( ( v1-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
453 _CalculateAxis(v1 , vCp0 , cData.vCylinderAxis , vAxis);
454 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 12))
455 {
456 return false;
457 }
458
459 // third vertex on triangle
460 // axis ((V2-Cp0) x C) x C
461 //vAxis = ( ( v2-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
462 _CalculateAxis(v2 , vCp0 , cData.vCylinderAxis , vAxis);
463 if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 13))
464 {
465 return false;
466 }
467
468 // test cylinder axis
469 // vAxis = cData.vCylinderAxis;
470 dVector3Copy(cData.vCylinderAxis , vAxis);
471 if (!_cldTestAxis(cData , v0, v1, v2, vAxis, 14))
472 {
473 return false;
474 }
475
476 // Test top and bottom circle ring of cylinder for separation
477 dVector3 vccATop;
478 vccATop[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize * REAL(0.5));
479 vccATop[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize * REAL(0.5));
480 vccATop[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize * REAL(0.5));
481
482 dVector3 vccABottom;
483 vccABottom[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize * REAL(0.5));
484 vccABottom[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize * REAL(0.5));
485 vccABottom[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize * REAL(0.5));
486
487
488 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v0, v1, 15))
489 {
490 return false;
491 }
492
493 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v1, v2, 16))
494 {
495 return false;
496 }
497
498 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v0, v2, 17))
499 {
500 return false;
501 }
502
503 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v0, v1, 18))
504 {
505 return false;
506 }
507
508 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v1, v2, 19))
509 {
510 return false;
511 }
512
513 if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v0, v2, 20))
514 {
515 return false;
516 }
517
518 return true;
519}
520
521bool _cldClipCylinderEdgeToTriangle(sData& cData, const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)
522{
523 // translate cylinder
524 dReal fTemp = dVector3Dot(cData.vCylinderAxis , cData.vContactNormal);
525 dVector3 vN2;
526 vN2[0] = cData.vContactNormal[0] - cData.vCylinderAxis[0]*fTemp;
527 vN2[1] = cData.vContactNormal[1] - cData.vCylinderAxis[1]*fTemp;
528 vN2[2] = cData.vContactNormal[2] - cData.vCylinderAxis[2]*fTemp;
529
530 fTemp = dVector3Length(vN2);
531 if (fTemp < REAL(1e-5))
532 {
533 return false;
534 }
535
536 // Normalize it
537 vN2[0] /= fTemp;
538 vN2[1] /= fTemp;
539 vN2[2] /= fTemp;
540
541 // calculate caps centers in absolute space
542 dVector3 vCposTrans;
543 vCposTrans[0] = cData.vCylinderPos[0] + vN2[0]*cData.fCylinderRadius;
544 vCposTrans[1] = cData.vCylinderPos[1] + vN2[1]*cData.fCylinderRadius;
545 vCposTrans[2] = cData.vCylinderPos[2] + vN2[2]*cData.fCylinderRadius;
546
547 dVector3 vCEdgePoint0;
548 vCEdgePoint0[0] = vCposTrans[0] + cData.vCylinderAxis[0] * (cData.fCylinderSize* REAL(0.5));
549 vCEdgePoint0[1] = vCposTrans[1] + cData.vCylinderAxis[1] * (cData.fCylinderSize* REAL(0.5));
550 vCEdgePoint0[2] = vCposTrans[2] + cData.vCylinderAxis[2] * (cData.fCylinderSize* REAL(0.5));
551
552 dVector3 vCEdgePoint1;
553 vCEdgePoint1[0] = vCposTrans[0] - cData.vCylinderAxis[0] * (cData.fCylinderSize* REAL(0.5));
554 vCEdgePoint1[1] = vCposTrans[1] - cData.vCylinderAxis[1] * (cData.fCylinderSize* REAL(0.5));
555 vCEdgePoint1[2] = vCposTrans[2] - cData.vCylinderAxis[2] * (cData.fCylinderSize* REAL(0.5));
556
557 // transform cylinder edge points into triangle space
558 vCEdgePoint0[0] -= v0[0];
559 vCEdgePoint0[1] -= v0[1];
560 vCEdgePoint0[2] -= v0[2];
561
562 vCEdgePoint1[0] -= v0[0];
563 vCEdgePoint1[1] -= v0[1];
564 vCEdgePoint1[2] -= v0[2];
565
566 dVector4 plPlane;
567 dVector3 vPlaneNormal;
568
569 // triangle plane
570 //plPlane = Plane4f( -cData.vNormal, 0);
571 vPlaneNormal[0] = -cData.vNormal[0];
572 vPlaneNormal[1] = -cData.vNormal[1];
573 vPlaneNormal[2] = -cData.vNormal[2];
574 dConstructPlane(vPlaneNormal,REAL(0.0),plPlane);
575 if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
576 {
577 return false;
578 }
579
580 // plane with edge 0
581 //plPlane = Plane4f( ( cData.vNormal cross cData.vE0 ), REAL(1e-5));
582 dVector3Cross(cData.vNormal,cData.vE0,vPlaneNormal);
583 dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane);
584 if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
585 {
586 return false;
587 }
588
589 // plane with edge 1
590 //dVector3 vTemp = ( cData.vNormal cross cData.vE1 );
591 dVector3Cross(cData.vNormal,cData.vE1,vPlaneNormal);
592 fTemp = dVector3Dot(cData.vE0 , vPlaneNormal) - REAL(1e-5);
593 //plPlane = Plane4f( vTemp, -(( cData.vE0 dot vTemp )-REAL(1e-5)));
594 dConstructPlane(vPlaneNormal,-fTemp,plPlane);
595 if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
596 {
597 return false;
598 }
599
600 // plane with edge 2
601 // plPlane = Plane4f( ( cData.vNormal cross cData.vE2 ), REAL(1e-5));
602 dVector3Cross(cData.vNormal,cData.vE2,vPlaneNormal);
603 dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane);
604 if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
605 {
606 return false;
607 }
608
609 // return capsule edge points into absolute space
610 vCEdgePoint0[0] += v0[0];
611 vCEdgePoint0[1] += v0[1];
612 vCEdgePoint0[2] += v0[2];
613
614 vCEdgePoint1[0] += v0[0];
615 vCEdgePoint1[1] += v0[1];
616 vCEdgePoint1[2] += v0[2];
617
618 // calculate depths for both contact points
619 dVector3 vTemp;
620 dVector3Subtract(vCEdgePoint0,cData.vCylinderPos, vTemp);
621 dReal fRestDepth0 = -dVector3Dot(vTemp,cData.vContactNormal) + cData.fBestrt;
622 dVector3Subtract(vCEdgePoint1,cData.vCylinderPos, vTemp);
623 dReal fRestDepth1 = -dVector3Dot(vTemp,cData.vContactNormal) + cData.fBestrt;
624
625 dReal fDepth0 = cData.fBestDepth - (fRestDepth0);
626 dReal fDepth1 = cData.fBestDepth - (fRestDepth1);
627
628 // clamp depths to zero
629 if(fDepth0 < REAL(0.0) )
630 {
631 fDepth0 = REAL(0.0);
632 }
633
634 if(fDepth1<REAL(0.0))
635 {
636 fDepth1 = REAL(0.0);
637 }
638
639 // Generate contact 0
640 {
641 cData.gLocalContacts[cData.nContacts].fDepth = fDepth0;
642 dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
643 dVector3Copy(vCEdgePoint0,cData.gLocalContacts[cData.nContacts].vPos);
644 cData.gLocalContacts[cData.nContacts].nFlags = 1;
645 cData.nContacts++;
646 if(cData.nContacts >= (cData.iFlags & NUMC_MASK))
647 return true;
648 }
649
650 // Generate contact 1
651 {
652 // generate contacts
653 cData.gLocalContacts[cData.nContacts].fDepth = fDepth1;
654 dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
655 dVector3Copy(vCEdgePoint1,cData.gLocalContacts[cData.nContacts].vPos);
656 cData.gLocalContacts[cData.nContacts].nFlags = 1;
657 cData.nContacts++;
658 }
659
660 return true;
661}
662
663void _cldClipCylinderToTriangle(sData& cData,const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)
664{
665 int i = 0;
666 dVector3 avPoints[3];
667 dVector3 avTempArray1[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS];
668 dVector3 avTempArray2[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS];
669
670 dSetZero(&avTempArray1[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4);
671 dSetZero(&avTempArray2[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4);
672
673 // setup array of triangle vertices
674 dVector3Copy(v0,avPoints[0]);
675 dVector3Copy(v1,avPoints[1]);
676 dVector3Copy(v2,avPoints[2]);
677
678 dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel;
679 dSetZero(vCylinderCircleNormal_Rel,4);
680 // check which circle from cylinder we take for clipping
681 if ( dVector3Dot(cData.vCylinderAxis , cData.vContactNormal) > REAL(0.0))
682 {
683 // get top circle
684 vCylinderCirclePos[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
685 vCylinderCirclePos[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
686 vCylinderCirclePos[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
687
688 vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0);
689 }
690 else
691 {
692 // get bottom circle
693 vCylinderCirclePos[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
694 vCylinderCirclePos[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
695 vCylinderCirclePos[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
696
697 vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0);
698 }
699
700 dVector3 vTemp;
701 dQuatInv(cData.qCylinderRot , cData.qInvCylinderRot);
702 // transform triangle points to space of cylinder circle
703 for(i=0; i<3; i++)
704 {
705 dVector3Subtract(avPoints[i] , vCylinderCirclePos , vTemp);
706 dQuatTransform(cData.qInvCylinderRot,vTemp,avPoints[i]);
707 }
708
709 int iTmpCounter1 = 0;
710 int iTmpCounter2 = 0;
711 dVector4 plPlane;
712
713 // plane of cylinder that contains circle for intersection
714 //plPlane = Plane4f( vCylinderCircleNormal_Rel, 0.0f );
715 dConstructPlane(vCylinderCircleNormal_Rel,REAL(0.0),plPlane);
716 dClipPolyToPlane(avPoints, 3, avTempArray1, iTmpCounter1, plPlane);
717
718 // Body of base circle of Cylinder
719 int nCircleSegment = 0;
720 for (nCircleSegment = 0; nCircleSegment < nCYLINDER_CIRCLE_SEGMENTS; nCircleSegment++)
721 {
722 dConstructPlane(cData.avCylinderNormals[nCircleSegment],cData.fCylinderRadius,plPlane);
723
724 if (0 == (nCircleSegment % 2))
725 {
726 dClipPolyToPlane( avTempArray1 , iTmpCounter1 , avTempArray2, iTmpCounter2, plPlane);
727 }
728 else
729 {
730 dClipPolyToPlane( avTempArray2, iTmpCounter2, avTempArray1 , iTmpCounter1 , plPlane );
731 }
732
733 dIASSERT( iTmpCounter1 >= 0 && iTmpCounter1 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS );
734 dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS );
735 }
736
737 // back transform clipped points to absolute space
738 dReal ftmpdot;
739 dReal fTempDepth;
740 dVector3 vPoint;
741
742 if (nCircleSegment %2)
743 {
744 for( i=0; i<iTmpCounter2; i++)
745 {
746 dQuatTransform(cData.qCylinderRot,avTempArray2[i], vPoint);
747 vPoint[0] += vCylinderCirclePos[0];
748 vPoint[1] += vCylinderCirclePos[1];
749 vPoint[2] += vCylinderCirclePos[2];
750
751 dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
752 ftmpdot = dFabs(dVector3Dot(vTemp, cData.vContactNormal));
753 fTempDepth = cData.fBestrt - ftmpdot;
754 // Depth must be positive
755 if (fTempDepth > REAL(0.0))
756 {
757 cData.gLocalContacts[cData.nContacts].fDepth = fTempDepth;
758 dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
759 dVector3Copy(vPoint,cData.gLocalContacts[cData.nContacts].vPos);
760 cData.gLocalContacts[cData.nContacts].nFlags = 1;
761 cData.nContacts++;
762 if(cData.nContacts >= (cData.iFlags & NUMC_MASK))
763 return;;
764 }
765 }
766 }
767 else
768 {
769 for( i=0; i<iTmpCounter1; i++)
770 {
771 dQuatTransform(cData.qCylinderRot,avTempArray1[i], vPoint);
772 vPoint[0] += vCylinderCirclePos[0];
773 vPoint[1] += vCylinderCirclePos[1];
774 vPoint[2] += vCylinderCirclePos[2];
775
776 dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
777 ftmpdot = dFabs(dVector3Dot(vTemp, cData.vContactNormal));
778 fTempDepth = cData.fBestrt - ftmpdot;
779 // Depth must be positive
780 if (fTempDepth > REAL(0.0))
781 {
782 cData.gLocalContacts[cData.nContacts].fDepth = fTempDepth;
783 dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
784 dVector3Copy(vPoint,cData.gLocalContacts[cData.nContacts].vPos);
785 cData.gLocalContacts[cData.nContacts].nFlags = 1;
786 cData.nContacts++;
787 if(cData.nContacts >= (cData.iFlags & NUMC_MASK))
788 return;;
789 }
790 }
791 }
792}
793
794void TestOneTriangleVsCylinder( sData& cData,
795 const dVector3 &v0,
796 const dVector3 &v1,
797 const dVector3 &v2,
798 const bool bDoubleSided)
799{
800
801 // calculate triangle normal
802 dVector3Subtract( v2 , v1 ,cData.vE1);
803 dVector3 vTemp;
804 dVector3Subtract( v0 , v1 ,vTemp);
805 dVector3Cross(cData.vE1 , vTemp , cData.vNormal );
806
807 dNormalize3( cData.vNormal);
808
809 // create plane from triangle
810 //Plane4f plTrianglePlane = Plane4f( vPolyNormal, v0 );
811 dReal plDistance = -dVector3Dot(v0, cData.vNormal);
812 dVector4 plTrianglePlane;
813 dConstructPlane( cData.vNormal,plDistance,plTrianglePlane);
814
815 // calculate sphere distance to plane
816 dReal fDistanceCylinderCenterToPlane = dPointPlaneDistance(cData.vCylinderPos , plTrianglePlane);
817
818 // Sphere must be over positive side of triangle
819 if(fDistanceCylinderCenterToPlane < 0 && !bDoubleSided)
820 {
821 // if not don't generate contacts
822 return;
823 }
824
825 dVector3 vPnt0;
826 dVector3 vPnt1;
827 dVector3 vPnt2;
828
829 if (fDistanceCylinderCenterToPlane < REAL(0.0) )
830 {
831 // flip it
832 dVector3Copy(v0 , vPnt0);
833 dVector3Copy(v1 , vPnt2);
834 dVector3Copy(v2 , vPnt1);
835 }
836 else
837 {
838 dVector3Copy(v0 , vPnt0);
839 dVector3Copy(v1 , vPnt1);
840 dVector3Copy(v2 , vPnt2);
841 }
842
843 cData.fBestDepth = MAX_REAL;
844
845 // do intersection test and find best separating axis
846 if(!_cldTestSeparatingAxes(cData , vPnt0, vPnt1, vPnt2) )
847 {
848 // if not found do nothing
849 return;
850 }
851
852 // if best separation axis is not found
853 if ( cData.iBestAxis == 0 )
854 {
855 // this should not happen (we should already exit in that case)
856 dIASSERT(false);
857 // do nothing
858 return;
859 }
860
861 dReal fdot = dVector3Dot( cData.vContactNormal , cData.vCylinderAxis );
862
863 // choose which clipping method are we going to apply
864 if (dFabs(fdot) < REAL(0.9) )
865 {
866 if (!_cldClipCylinderEdgeToTriangle(cData ,vPnt0, vPnt1, vPnt2))
867 {
868 return;
869 }
870 }
871 else
872 {
873 _cldClipCylinderToTriangle(cData ,vPnt0, vPnt1, vPnt2);
874 }
875
876}
877
878void _InitCylinderTrimeshData(sData& cData)
879{
880 // get cylinder information
881 // Rotation
882 const dReal* pRotCyc = dGeomGetRotation(cData.gCylinder);
883 dMatrix3Copy(pRotCyc,cData.mCylinderRot);
884 dGeomGetQuaternion(cData.gCylinder,cData.qCylinderRot);
885
886 // Position
887 const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(cData.gCylinder);
888 dVector3Copy(*pPosCyc,cData.vCylinderPos);
889 // Cylinder axis
890 dMat3GetCol(cData.mCylinderRot,nCYLINDER_AXIS,cData.vCylinderAxis);
891 // get cylinder radius and size
892 dGeomCylinderGetParams(cData.gCylinder,&cData.fCylinderRadius,&cData.fCylinderSize);
893
894 // get trimesh position and orientation
895 const dReal* pRotTris = dGeomGetRotation(cData.gTrimesh);
896 dMatrix3Copy(pRotTris,cData.mTrimeshRot);
897 dGeomGetQuaternion(cData.gTrimesh,cData.qTrimeshRot);
898
899 // Position
900 const dVector3* pPosTris = (const dVector3*)dGeomGetPosition(cData.gTrimesh);
901 dVector3Copy(*pPosTris,cData.vTrimeshPos);
902
903
904 // calculate basic angle for 8-gon
905 dReal fAngle = M_PI / nCYLINDER_CIRCLE_SEGMENTS;
906 // calculate angle increment
907 dReal fAngleIncrement = fAngle*REAL(2.0);
908
909 // calculate plane normals
910 // axis dependant code
911 for(int i=0; i<nCYLINDER_CIRCLE_SEGMENTS; i++)
912 {
913 cData.avCylinderNormals[i][0] = -dCos(fAngle);
914 cData.avCylinderNormals[i][1] = -dSin(fAngle);
915 cData.avCylinderNormals[i][2] = REAL(0.0);
916
917 fAngle += fAngleIncrement;
918 }
919
920 dSetZero(cData.vBestPoint,4);
921 // reset best depth
922 cData.fBestCenter = REAL(0.0);
923}
924
925#if dTRIMESH_ENABLED
926
927// OPCODE version of cylinder to mesh collider
928#if dTRIMESH_OPCODE
929int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
930{
931 dIASSERT( skip >= (int)sizeof( dContactGeom ) );
932 dIASSERT( o1->type == dCylinderClass );
933 dIASSERT( o2->type == dTriMeshClass );
934 dIASSERT ((flags & NUMC_MASK) >= 1);
935
936 // Main data holder
937 sData cData;
938
939 // Assign ODE stuff
940 cData.gCylinder = o1;
941 cData.gTrimesh = (dxTriMesh*)o2;
942 cData.iFlags = flags;
943 cData.iSkip = skip;
944 cData.gContact = contact;
945 cData.nContacts = 0;
946
947 _InitCylinderTrimeshData(cData);
948
949 OBBCollider& Collider = cData.gTrimesh->_OBBCollider;
950
951 Point cCenter(cData.vCylinderPos[0],cData.vCylinderPos[1],cData.vCylinderPos[2]);
952
953 Point cExtents(cData.fCylinderRadius,cData.fCylinderRadius,cData.fCylinderRadius);
954 cExtents[nCYLINDER_AXIS] = cData.fCylinderSize * REAL(0.5);
955
956 Matrix3x3 obbRot;
957
958 // It is a potential issue to explicitly cast to float
959 // if custom width floating point type is introduced in OPCODE.
960 // It is necessary to make a typedef and cast to it
961 // (e.g. typedef float opc_float;)
962 // However I'm not sure in what header it should be added.
963
964 obbRot[0][0] = /*(float)*/cData.mCylinderRot[0];
965 obbRot[1][0] = /*(float)*/cData.mCylinderRot[1];
966 obbRot[2][0] = /*(float)*/cData.mCylinderRot[2];
967
968 obbRot[0][1] = /*(float)*/cData.mCylinderRot[4];
969 obbRot[1][1] = /*(float)*/cData.mCylinderRot[5];
970 obbRot[2][1] = /*(float)*/cData.mCylinderRot[6];
971
972 obbRot[0][2] = /*(float)*/cData.mCylinderRot[8];
973 obbRot[1][2] = /*(float)*/cData.mCylinderRot[9];
974 obbRot[2][2] = /*(float)*/cData.mCylinderRot[10];
975
976 OBB obbCapsule(cCenter,cExtents,obbRot);
977
978 Matrix4x4 CapsuleMatrix;
979 MakeMatrix(cData.vCylinderPos, cData.mCylinderRot, CapsuleMatrix);
980
981 Matrix4x4 MeshMatrix;
982 MakeMatrix(cData.vTrimeshPos, cData.mTrimeshRot, MeshMatrix);
983
984 // TC results
985 if (cData.gTrimesh->doBoxTC)
986 {
987 dxTriMesh::BoxTC* BoxTC = 0;
988 for (int i = 0; i < cData.gTrimesh->BoxTCCache.size(); i++)
989 {
990 if (cData.gTrimesh->BoxTCCache[i].Geom == cData.gCylinder)
991 {
992 BoxTC = &cData.gTrimesh->BoxTCCache[i];
993 break;
994 }
995 }
996 if (!BoxTC)
997 {
998 cData.gTrimesh->BoxTCCache.push(dxTriMesh::BoxTC());
999
1000 BoxTC = &cData.gTrimesh->BoxTCCache[cData.gTrimesh->BoxTCCache.size() - 1];
1001 BoxTC->Geom = cData.gCylinder;
1002 BoxTC->FatCoeff = REAL(1.0);
1003 }
1004
1005 // Intersect
1006 Collider.SetTemporalCoherence(true);
1007 Collider.Collide(*BoxTC, obbCapsule, cData.gTrimesh->Data->BVTree, null, &MeshMatrix);
1008 }
1009 else
1010 {
1011 Collider.SetTemporalCoherence(false);
1012 Collider.Collide(dxTriMesh::defaultBoxCache, obbCapsule, cData.gTrimesh->Data->BVTree, null,&MeshMatrix);
1013 }
1014
1015 // Retrieve data
1016 int TriCount = Collider.GetNbTouchedPrimitives();
1017 const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
1018
1019
1020 if (TriCount != 0)
1021 {
1022 if (cData.gTrimesh->ArrayCallback != null)
1023 {
1024 cData.gTrimesh->ArrayCallback(cData.gTrimesh, cData.gCylinder, Triangles, TriCount);
1025 }
1026
1027 // allocate buffer for local contacts on stack
1028 cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK));
1029
1030 int ctContacts0 = 0;
1031
1032 // loop through all intersecting triangles
1033 for (int i = 0; i < TriCount; i++)
1034 {
1035 const int Triint = Triangles[i];
1036 if (!Callback(cData.gTrimesh, cData.gCylinder, Triint)) continue;
1037
1038
1039 dVector3 dv[3];
1040 FetchTriangle(cData.gTrimesh, Triint, cData.vTrimeshPos, cData.mTrimeshRot, dv);
1041
1042 // test this triangle
1043 TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false);
1044
1045 // fill-in tri index for generated contacts
1046 for (; ctContacts0<cData.nContacts; ctContacts0++)
1047 cData.gLocalContacts[ctContacts0].triIndex = Triint;
1048
1049 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
1050 if(cData.nContacts >= (cData.iFlags & NUMC_MASK))
1051 {
1052 break;
1053 }
1054 }
1055 }
1056
1057 return _ProcessLocalContacts(cData);
1058}
1059#endif
1060
1061// GIMPACT version of cylinder to mesh collider
1062#if dTRIMESH_GIMPACT
1063int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
1064{
1065 dIASSERT( skip >= (int)sizeof( dContactGeom ) );
1066 dIASSERT( o1->type == dCylinderClass );
1067 dIASSERT( o2->type == dTriMeshClass );
1068 dIASSERT ((flags & NUMC_MASK) >= 1);
1069
1070 // Main data holder
1071 sData cData;
1072
1073 // Assign ODE stuff
1074 cData.gCylinder = o1;
1075 cData.gTrimesh = (dxTriMesh*)o2;
1076 cData.iFlags = flags;
1077 cData.iSkip = skip;
1078 cData.gContact = contact;
1079 cData.nContacts = 0;
1080
1081 _InitCylinderTrimeshData(cData);
1082
1083//*****at first , collide box aabb******//
1084
1085 aabb3f test_aabb;
1086
1087 test_aabb.minX = o1->aabb[0];
1088 test_aabb.maxX = o1->aabb[1];
1089 test_aabb.minY = o1->aabb[2];
1090 test_aabb.maxY = o1->aabb[3];
1091 test_aabb.minZ = o1->aabb[4];
1092 test_aabb.maxZ = o1->aabb[5];
1093
1094
1095 GDYNAMIC_ARRAY collision_result;
1096 GIM_CREATE_BOXQUERY_LIST(collision_result);
1097
1098 gim_aabbset_box_collision(&test_aabb, &cData.gTrimesh->m_collision_trimesh.m_aabbset , &collision_result);
1099
1100 if(collision_result.m_size==0)
1101 {
1102 GIM_DYNARRAY_DESTROY(collision_result);
1103 return 0;
1104 }
1105//*****Set globals for box collision******//
1106
1107 int ctContacts0 = 0;
1108 cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK));
1109
1110 GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
1111 GIM_TRIMESH * ptrimesh = &cData.gTrimesh->m_collision_trimesh;
1112
1113 gim_trimesh_locks_work_data(ptrimesh);
1114
1115
1116 for(unsigned int i=0;i<collision_result.m_size;i++)
1117 {
1118 const int Triint = boxesresult[i];
1119
1120 dVector3 dv[3];
1121 gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]);
1122 // test this triangle
1123 TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false);
1124
1125 // fill-in triangle index for generated contacts
1126 for (; ctContacts0<cData.nContacts; ctContacts0++)
1127 cData.gLocalContacts[ctContacts0].triIndex = Triint;
1128
1129 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
1130 if(cData.nContacts >= (cData.iFlags & NUMC_MASK))
1131 {
1132 break;
1133 }
1134 }
1135
1136 gim_trimesh_unlocks_work_data(ptrimesh);
1137 GIM_DYNARRAY_DESTROY(collision_result);
1138
1139 return _ProcessLocalContacts(cData);
1140}
1141#endif
1142
1143#endif // dTRIMESH_ENABLED
1144
1145
diff --git a/libraries/ode-0.9/ode/src/collision_kernel.cpp b/libraries/ode-0.9/ode/src/collision_kernel.cpp
deleted file mode 100644
index b885603..0000000
--- a/libraries/ode-0.9/ode/src/collision_kernel.cpp
+++ /dev/null
@@ -1,1103 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25core collision functions and data structures, plus part of the public API
26for geometry objects
27
28*/
29
30#include <ode/common.h>
31#include <ode/matrix.h>
32#include <ode/rotation.h>
33#include <ode/objects.h>
34#include <ode/odemath.h>
35#include "collision_kernel.h"
36#include "collision_util.h"
37#include "collision_std.h"
38#include "collision_transform.h"
39#include "collision_trimesh_internal.h"
40
41#if dTRIMESH_GIMPACT
42#include <GIMPACT/gimpact.h>
43#endif
44
45#ifdef _MSC_VER
46#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
47#endif
48
49//****************************************************************************
50// helper functions for dCollide()ing a space with another geom
51
52// this struct records the parameters passed to dCollideSpaceGeom()
53
54// Allocate and free posr - we cache a single posr to avoid thrashing
55static dxPosR* s_cachedPosR = 0;
56
57dxPosR* dAllocPosr()
58{
59 dxPosR* retPosR;
60 if (s_cachedPosR)
61 {
62 retPosR = s_cachedPosR;
63 s_cachedPosR = 0;
64 }
65 else
66 {
67 retPosR = (dxPosR*) dAlloc (sizeof(dxPosR));
68 }
69 return retPosR;
70}
71
72void dFreePosr(dxPosR* oldPosR)
73{
74 if (oldPosR)
75 {
76 if (s_cachedPosR)
77 {
78 dFree(s_cachedPosR, sizeof(dxPosR));
79 }
80 s_cachedPosR = oldPosR;
81 }
82}
83
84void dClearPosrCache(void)
85{
86 if (s_cachedPosR)
87 {
88 dFree(s_cachedPosR, sizeof(dxPosR));
89 s_cachedPosR = 0;
90 }
91}
92
93struct SpaceGeomColliderData {
94 int flags; // space left in contacts array
95 dContactGeom *contact;
96 int skip;
97};
98
99
100static void space_geom_collider (void *data, dxGeom *o1, dxGeom *o2)
101{
102 SpaceGeomColliderData *d = (SpaceGeomColliderData*) data;
103 if (d->flags & NUMC_MASK) {
104 int n = dCollide (o1,o2,d->flags,d->contact,d->skip);
105 d->contact = CONTACT (d->contact,d->skip*n);
106 d->flags -= n;
107 }
108}
109
110
111static int dCollideSpaceGeom (dxGeom *o1, dxGeom *o2, int flags,
112 dContactGeom *contact, int skip)
113{
114 SpaceGeomColliderData data;
115 data.flags = flags;
116 data.contact = contact;
117 data.skip = skip;
118 dSpaceCollide2 (o1,o2,&data,&space_geom_collider);
119 return (flags & NUMC_MASK) - (data.flags & NUMC_MASK);
120}
121
122//****************************************************************************
123// dispatcher for the N^2 collider functions
124
125// function pointers and modes for n^2 class collider functions
126
127struct dColliderEntry {
128 dColliderFn *fn; // collider function, 0 = no function available
129 int reverse; // 1 = reverse o1 and o2
130};
131static dColliderEntry colliders[dGeomNumClasses][dGeomNumClasses];
132static int colliders_initialized = 0;
133
134
135// setCollider() will refuse to write over a collider entry once it has
136// been written.
137
138static void setCollider (int i, int j, dColliderFn *fn)
139{
140 if (colliders[i][j].fn == 0) {
141 colliders[i][j].fn = fn;
142 colliders[i][j].reverse = 0;
143 }
144 if (colliders[j][i].fn == 0) {
145 colliders[j][i].fn = fn;
146 colliders[j][i].reverse = 1;
147 }
148}
149
150
151static void setAllColliders (int i, dColliderFn *fn)
152{
153 for (int j=0; j<dGeomNumClasses; j++) setCollider (i,j,fn);
154}
155
156
157static void initColliders()
158{
159 int i,j;
160
161 if (colliders_initialized) return;
162 colliders_initialized = 1;
163
164 memset (colliders,0,sizeof(colliders));
165
166 // setup space colliders
167 for (i=dFirstSpaceClass; i <= dLastSpaceClass; i++) {
168 for (j=0; j < dGeomNumClasses; j++) {
169 setCollider (i,j,&dCollideSpaceGeom);
170 }
171 }
172
173 setCollider (dSphereClass,dSphereClass,&dCollideSphereSphere);
174 setCollider (dSphereClass,dBoxClass,&dCollideSphereBox);
175 setCollider (dSphereClass,dPlaneClass,&dCollideSpherePlane);
176 setCollider (dBoxClass,dBoxClass,&dCollideBoxBox);
177 setCollider (dBoxClass,dPlaneClass,&dCollideBoxPlane);
178 setCollider (dCapsuleClass,dSphereClass,&dCollideCapsuleSphere);
179 setCollider (dCapsuleClass,dBoxClass,&dCollideCapsuleBox);
180 setCollider (dCapsuleClass,dCapsuleClass,&dCollideCapsuleCapsule);
181 setCollider (dCapsuleClass,dPlaneClass,&dCollideCapsulePlane);
182 setCollider (dRayClass,dSphereClass,&dCollideRaySphere);
183 setCollider (dRayClass,dBoxClass,&dCollideRayBox);
184 setCollider (dRayClass,dCapsuleClass,&dCollideRayCapsule);
185 setCollider (dRayClass,dPlaneClass,&dCollideRayPlane);
186 setCollider (dRayClass,dCylinderClass,&dCollideRayCylinder);
187#if dTRIMESH_ENABLED
188 setCollider (dTriMeshClass,dSphereClass,&dCollideSTL);
189 setCollider (dTriMeshClass,dBoxClass,&dCollideBTL);
190 setCollider (dTriMeshClass,dRayClass,&dCollideRTL);
191 setCollider (dTriMeshClass,dTriMeshClass,&dCollideTTL);
192 setCollider (dTriMeshClass,dCapsuleClass,&dCollideCCTL);
193 setCollider (dTriMeshClass,dPlaneClass,&dCollideTrimeshPlane);
194 setCollider (dCylinderClass,dTriMeshClass,&dCollideCylinderTrimesh);
195#endif
196 setCollider (dCylinderClass,dBoxClass,&dCollideCylinderBox);
197 setCollider (dCylinderClass,dSphereClass,&dCollideCylinderSphere);
198 setCollider (dCylinderClass,dPlaneClass,&dCollideCylinderPlane);
199 //setCollider (dCylinderClass,dCylinderClass,&dCollideCylinderCylinder);
200
201//--> Convex Collision
202 setCollider (dConvexClass,dPlaneClass,&dCollideConvexPlane);
203 setCollider (dSphereClass,dConvexClass,&dCollideSphereConvex);
204 setCollider (dConvexClass,dBoxClass,&dCollideConvexBox);
205 setCollider (dConvexClass,dCapsuleClass,&dCollideConvexCapsule);
206 setCollider (dConvexClass,dConvexClass,&dCollideConvexConvex);
207 setCollider (dRayClass,dConvexClass,&dCollideRayConvex);
208//<-- Convex Collision
209
210//--> dHeightfield Collision
211 setCollider (dHeightfieldClass,dRayClass,&dCollideHeightfield);
212 setCollider (dHeightfieldClass,dSphereClass,&dCollideHeightfield);
213 setCollider (dHeightfieldClass,dBoxClass,&dCollideHeightfield);
214 setCollider (dHeightfieldClass,dCapsuleClass,&dCollideHeightfield);
215 setCollider (dHeightfieldClass,dCylinderClass,&dCollideHeightfield);
216 setCollider (dHeightfieldClass,dConvexClass,&dCollideHeightfield);
217#if dTRIMESH_ENABLED
218 setCollider (dHeightfieldClass,dTriMeshClass,&dCollideHeightfield);
219#endif
220//<-- dHeightfield Collision
221
222 setAllColliders (dGeomTransformClass,&dCollideTransform);
223}
224
225
226/*
227 * NOTE!
228 * If it is necessary to add special processing mode without contact generation
229 * use NULL contact parameter value as indicator, not zero in flags.
230 */
231int dCollide (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact,
232 int skip)
233{
234 dAASSERT(o1 && o2 && contact);
235 dUASSERT(colliders_initialized,"colliders array not initialized");
236 dUASSERT(o1->type >= 0 && o1->type < dGeomNumClasses,"bad o1 class number");
237 dUASSERT(o2->type >= 0 && o2->type < dGeomNumClasses,"bad o2 class number");
238 // Even though comparison for greater or equal to one is used in all the
239 // other places, here it is more logical to check for greater than zero
240 // because function does not require any specific number of contact slots -
241 // it must be just a positive.
242 dUASSERT((flags & NUMC_MASK) > 0, "no contacts requested");
243
244 // Extra precaution for zero contact count in parameters
245 if ((flags & NUMC_MASK) == 0) return 0;
246 // no contacts if both geoms are the same
247 if (o1 == o2) return 0;
248
249 // no contacts if both geoms on the same body, and the body is not 0
250 if (o1->body == o2->body && o1->body) return 0;
251
252 o1->recomputePosr();
253 o2->recomputePosr();
254
255 dColliderEntry *ce = &colliders[o1->type][o2->type];
256 int count = 0;
257 if (ce->fn) {
258 if (ce->reverse) {
259 count = (*ce->fn) (o2,o1,flags,contact,skip);
260 for (int i=0; i<count; i++) {
261 dContactGeom *c = CONTACT(contact,skip*i);
262 c->normal[0] = -c->normal[0];
263 c->normal[1] = -c->normal[1];
264 c->normal[2] = -c->normal[2];
265 dxGeom *tmp = c->g1;
266 c->g1 = c->g2;
267 c->g2 = tmp;
268 int tmpint = c->side1;
269 c->side1 = c->side2;
270 c->side2 = tmpint;
271 }
272 }
273 else {
274 count = (*ce->fn) (o1,o2,flags,contact,skip);
275 }
276 }
277 return count;
278}
279
280//****************************************************************************
281// dxGeom
282
283dxGeom::dxGeom (dSpaceID _space, int is_placeable)
284{
285 initColliders();
286
287 // setup body vars. invalid type of -1 must be changed by the constructor.
288 type = -1;
289 gflags = GEOM_DIRTY | GEOM_AABB_BAD | GEOM_ENABLED;
290 if (is_placeable) gflags |= GEOM_PLACEABLE;
291 data = 0;
292 body = 0;
293 body_next = 0;
294 if (is_placeable) {
295 final_posr = dAllocPosr();
296 dSetZero (final_posr->pos,4);
297 dRSetIdentity (final_posr->R);
298 }
299 else {
300 final_posr = 0;
301 }
302 offset_posr = 0;
303
304 // setup space vars
305 next = 0;
306 tome = 0;
307 parent_space = 0;
308 dSetZero (aabb,6);
309 category_bits = ~0;
310 collide_bits = ~0;
311
312 // put this geom in a space if required
313 if (_space) dSpaceAdd (_space,this);
314}
315
316
317dxGeom::~dxGeom()
318{
319 if (parent_space) dSpaceRemove (parent_space,this);
320 if ((gflags & GEOM_PLACEABLE) && (!body || (body && offset_posr)))
321 dFreePosr(final_posr);
322 if (offset_posr) dFreePosr(offset_posr);
323 bodyRemove();
324}
325
326
327int dxGeom::AABBTest (dxGeom *o, dReal aabb[6])
328{
329 return 1;
330}
331
332
333void dxGeom::bodyRemove()
334{
335 if (body) {
336 // delete this geom from body list
337 dxGeom **last = &body->geom, *g = body->geom;
338 while (g) {
339 if (g == this) {
340 *last = g->body_next;
341 break;
342 }
343 last = &g->body_next;
344 g = g->body_next;
345 }
346 body = 0;
347 body_next = 0;
348 }
349}
350
351inline void myswap(dReal& a, dReal& b) { dReal t=b; b=a; a=t; }
352
353
354inline void matrixInvert(const dMatrix3& inMat, dMatrix3& outMat)
355{
356 memcpy(outMat, inMat, sizeof(dMatrix3));
357 // swap _12 and _21
358 myswap(outMat[0 + 4*1], outMat[1 + 4*0]);
359 // swap _31 and _13
360 myswap(outMat[2 + 4*0], outMat[0 + 4*2]);
361 // swap _23 and _32
362 myswap(outMat[1 + 4*2], outMat[2 + 4*1]);
363}
364
365void getBodyPosr(const dxPosR& offset_posr, const dxPosR& final_posr, dxPosR& body_posr)
366{
367 dMatrix3 inv_offset;
368 matrixInvert(offset_posr.R, inv_offset);
369
370 dMULTIPLY0_333(body_posr.R, final_posr.R, inv_offset);
371 dVector3 world_offset;
372 dMULTIPLY0_331(world_offset, body_posr.R, offset_posr.pos);
373 body_posr.pos[0] = final_posr.pos[0] - world_offset[0];
374 body_posr.pos[1] = final_posr.pos[1] - world_offset[1];
375 body_posr.pos[2] = final_posr.pos[2] - world_offset[2];
376}
377
378void getWorldOffsetPosr(const dxPosR& body_posr, const dxPosR& world_posr, dxPosR& offset_posr)
379{
380 dMatrix3 inv_body;
381 matrixInvert(body_posr.R, inv_body);
382
383 dMULTIPLY0_333(offset_posr.R, inv_body, world_posr.R);
384 dVector3 world_offset;
385 world_offset[0] = world_posr.pos[0] - body_posr.pos[0];
386 world_offset[1] = world_posr.pos[1] - body_posr.pos[1];
387 world_offset[2] = world_posr.pos[2] - body_posr.pos[2];
388 dMULTIPLY0_331(offset_posr.pos, inv_body, world_offset);
389}
390
391void dxGeom::computePosr()
392{
393 // should only be recalced if we need to - ie offset from a body
394 dIASSERT(offset_posr);
395 dIASSERT(body);
396
397 dMULTIPLY0_331 (final_posr->pos,body->posr.R,offset_posr->pos);
398 final_posr->pos[0] += body->posr.pos[0];
399 final_posr->pos[1] += body->posr.pos[1];
400 final_posr->pos[2] += body->posr.pos[2];
401 dMULTIPLY0_333 (final_posr->R,body->posr.R,offset_posr->R);
402}
403
404//****************************************************************************
405// misc
406
407dxGeom *dGeomGetBodyNext (dxGeom *geom)
408{
409 return geom->body_next;
410}
411
412//****************************************************************************
413// public API for geometry objects
414
415#define CHECK_NOT_LOCKED(space) \
416 dUASSERT (!(space && space->lock_count), \
417 "invalid operation for geom in locked space");
418
419
420void dGeomDestroy (dxGeom *g)
421{
422 dAASSERT (g);
423 delete g;
424}
425
426
427void dGeomSetData (dxGeom *g, void *data)
428{
429 dAASSERT (g);
430 g->data = data;
431}
432
433
434void *dGeomGetData (dxGeom *g)
435{
436 dAASSERT (g);
437 return g->data;
438}
439
440
441void dGeomSetBody (dxGeom *g, dxBody *b)
442{
443 dAASSERT (g);
444 dUASSERT (b == NULL || (g->gflags & GEOM_PLACEABLE),"geom must be placeable");
445 CHECK_NOT_LOCKED (g->parent_space);
446
447 if (b) {
448 if (!g->body) dFreePosr(g->final_posr);
449 if (g->body != b) {
450 if (g->offset_posr) {
451 dFreePosr(g->offset_posr);
452 g->offset_posr = 0;
453 }
454 g->final_posr = &b->posr;
455 g->bodyRemove();
456 g->bodyAdd (b);
457 }
458 dGeomMoved (g);
459 }
460 else {
461 if (g->body) {
462 if (g->offset_posr)
463 {
464 // if we're offset, we already have our own final position, make sure its updated
465 g->recomputePosr();
466 dFreePosr(g->offset_posr);
467 g->offset_posr = 0;
468 }
469 else
470 {
471 g->final_posr = dAllocPosr();
472 memcpy (g->final_posr->pos,g->body->posr.pos,sizeof(dVector3));
473 memcpy (g->final_posr->R,g->body->posr.R,sizeof(dMatrix3));
474 }
475 g->bodyRemove();
476 }
477 // dGeomMoved() should not be called if the body is being set to 0, as the
478 // new position of the geom is set to the old position of the body, so the
479 // effective position of the geom remains unchanged.
480 }
481}
482
483
484dBodyID dGeomGetBody (dxGeom *g)
485{
486 dAASSERT (g);
487 return g->body;
488}
489
490
491void dGeomSetPosition (dxGeom *g, dReal x, dReal y, dReal z)
492{
493 dAASSERT (g);
494 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
495 CHECK_NOT_LOCKED (g->parent_space);
496 if (g->offset_posr) {
497 // move body such that body+offset = position
498 dVector3 world_offset;
499 dMULTIPLY0_331(world_offset, g->body->posr.R, g->offset_posr->pos);
500 dBodySetPosition(g->body,
501 x - world_offset[0],
502 y - world_offset[1],
503 z - world_offset[2]);
504 }
505 else if (g->body) {
506 // this will call dGeomMoved (g), so we don't have to
507 dBodySetPosition (g->body,x,y,z);
508 }
509 else {
510 g->final_posr->pos[0] = x;
511 g->final_posr->pos[1] = y;
512 g->final_posr->pos[2] = z;
513 dGeomMoved (g);
514 }
515}
516
517
518void dGeomSetRotation (dxGeom *g, const dMatrix3 R)
519{
520 dAASSERT (g && R);
521 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
522 CHECK_NOT_LOCKED (g->parent_space);
523 if (g->offset_posr) {
524 g->recomputePosr();
525 // move body such that body+offset = rotation
526 dxPosR new_final_posr;
527 dxPosR new_body_posr;
528 memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
529 memcpy(new_final_posr.R, R, sizeof(dMatrix3));
530 getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr);
531 dBodySetRotation(g->body, new_body_posr.R);
532 dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]);
533 }
534 else if (g->body) {
535 // this will call dGeomMoved (g), so we don't have to
536 dBodySetRotation (g->body,R);
537 }
538 else {
539 memcpy (g->final_posr->R,R,sizeof(dMatrix3));
540 dGeomMoved (g);
541 }
542}
543
544
545void dGeomSetQuaternion (dxGeom *g, const dQuaternion quat)
546{
547 dAASSERT (g && quat);
548 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
549 CHECK_NOT_LOCKED (g->parent_space);
550 if (g->offset_posr) {
551 g->recomputePosr();
552 // move body such that body+offset = rotation
553 dxPosR new_final_posr;
554 dxPosR new_body_posr;
555 dQtoR (quat, new_final_posr.R);
556 memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
557
558 getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr);
559 dBodySetRotation(g->body, new_body_posr.R);
560 dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]);
561 }
562 if (g->body) {
563 // this will call dGeomMoved (g), so we don't have to
564 dBodySetQuaternion (g->body,quat);
565 }
566 else {
567 dQtoR (quat, g->final_posr->R);
568 dGeomMoved (g);
569 }
570}
571
572
573const dReal * dGeomGetPosition (dxGeom *g)
574{
575 dAASSERT (g);
576 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
577 g->recomputePosr();
578 return g->final_posr->pos;
579}
580
581
582void dGeomCopyPosition(dxGeom *g, dVector3 pos)
583{
584 dAASSERT (g);
585 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
586 g->recomputePosr();
587 const dReal* src = g->final_posr->pos;
588 pos[0] = src[0];
589 pos[1] = src[1];
590 pos[2] = src[2];
591}
592
593
594const dReal * dGeomGetRotation (dxGeom *g)
595{
596 dAASSERT (g);
597 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
598 g->recomputePosr();
599 return g->final_posr->R;
600}
601
602
603void dGeomCopyRotation(dxGeom *g, dMatrix3 R)
604{
605 dAASSERT (g);
606 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
607 g->recomputePosr();
608 const dReal* src = g->final_posr->R;
609 R[0] = src[0];
610 R[1] = src[1];
611 R[2] = src[2];
612 R[4] = src[4];
613 R[5] = src[5];
614 R[6] = src[6];
615 R[8] = src[8];
616 R[9] = src[9];
617 R[10] = src[10];
618}
619
620
621void dGeomGetQuaternion (dxGeom *g, dQuaternion quat)
622{
623 dAASSERT (g);
624 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
625 if (g->body && !g->offset_posr) {
626 const dReal * body_quat = dBodyGetQuaternion (g->body);
627 quat[0] = body_quat[0];
628 quat[1] = body_quat[1];
629 quat[2] = body_quat[2];
630 quat[3] = body_quat[3];
631 }
632 else {
633 g->recomputePosr();
634 dRtoQ (g->final_posr->R, quat);
635 }
636}
637
638
639void dGeomGetAABB (dxGeom *g, dReal aabb[6])
640{
641 dAASSERT (g);
642 dAASSERT (aabb);
643 g->recomputeAABB();
644 memcpy (aabb,g->aabb,6 * sizeof(dReal));
645}
646
647
648int dGeomIsSpace (dxGeom *g)
649{
650 dAASSERT (g);
651 return IS_SPACE(g);
652}
653
654
655dSpaceID dGeomGetSpace (dxGeom *g)
656{
657 dAASSERT (g);
658 return g->parent_space;
659}
660
661
662int dGeomGetClass (dxGeom *g)
663{
664 dAASSERT (g);
665 return g->type;
666}
667
668
669void dGeomSetCategoryBits (dxGeom *g, unsigned long bits)
670{
671 dAASSERT (g);
672 CHECK_NOT_LOCKED (g->parent_space);
673 g->category_bits = bits;
674}
675
676
677void dGeomSetCollideBits (dxGeom *g, unsigned long bits)
678{
679 dAASSERT (g);
680 CHECK_NOT_LOCKED (g->parent_space);
681 g->collide_bits = bits;
682}
683
684
685unsigned long dGeomGetCategoryBits (dxGeom *g)
686{
687 dAASSERT (g);
688 return g->category_bits;
689}
690
691
692unsigned long dGeomGetCollideBits (dxGeom *g)
693{
694 dAASSERT (g);
695 return g->collide_bits;
696}
697
698
699void dGeomEnable (dxGeom *g)
700{
701 dAASSERT (g);
702 g->gflags |= GEOM_ENABLED;
703}
704
705void dGeomDisable (dxGeom *g)
706{
707 dAASSERT (g);
708 g->gflags &= ~GEOM_ENABLED;
709}
710
711int dGeomIsEnabled (dxGeom *g)
712{
713 dAASSERT (g);
714 return (g->gflags & GEOM_ENABLED) != 0;
715}
716
717
718//****************************************************************************
719// C interface that lets the user make new classes. this interface is a lot
720// more cumbersome than C++ subclassing, which is what is used internally
721// in ODE. this API is mainly to support legacy code.
722
723static int num_user_classes = 0;
724static dGeomClass user_classes [dMaxUserClasses];
725
726
727struct dxUserGeom : public dxGeom {
728 void *user_data;
729
730 dxUserGeom (int class_num);
731 ~dxUserGeom();
732 void computeAABB();
733 int AABBTest (dxGeom *o, dReal aabb[6]);
734};
735
736
737dxUserGeom::dxUserGeom (int class_num) : dxGeom (0,1)
738{
739 type = class_num;
740 int size = user_classes[type-dFirstUserClass].bytes;
741 user_data = dAlloc (size);
742 memset (user_data,0,size);
743}
744
745
746dxUserGeom::~dxUserGeom()
747{
748 dGeomClass *c = &user_classes[type-dFirstUserClass];
749 if (c->dtor) c->dtor (this);
750 dFree (user_data,c->bytes);
751}
752
753
754void dxUserGeom::computeAABB()
755{
756 user_classes[type-dFirstUserClass].aabb (this,aabb);
757}
758
759
760int dxUserGeom::AABBTest (dxGeom *o, dReal aabb[6])
761{
762 dGeomClass *c = &user_classes[type-dFirstUserClass];
763 if (c->aabb_test) return c->aabb_test (this,o,aabb);
764 else return 1;
765}
766
767
768static int dCollideUserGeomWithGeom (dxGeom *o1, dxGeom *o2, int flags,
769 dContactGeom *contact, int skip)
770{
771 // this generic collider function is called the first time that a user class
772 // tries to collide against something. it will find out the correct collider
773 // function and then set the colliders array so that the correct function is
774 // called directly the next time around.
775
776 int t1 = o1->type; // note that o1 is a user geom
777 int t2 = o2->type; // o2 *may* be a user geom
778
779 // find the collider function to use. if o1 does not know how to collide with
780 // o2, then o2 might know how to collide with o1 (provided that it is a user
781 // geom).
782 dColliderFn *fn = user_classes[t1-dFirstUserClass].collider (t2);
783 int reverse = 0;
784 if (!fn && t2 >= dFirstUserClass && t2 <= dLastUserClass) {
785 fn = user_classes[t2-dFirstUserClass].collider (t1);
786 reverse = 1;
787 }
788
789 // set the colliders array so that the correct function is called directly
790 // the next time around. note that fn can be 0 here if no collider was found,
791 // which means that dCollide() will always return 0 for this case.
792 colliders[t1][t2].fn = fn;
793 colliders[t1][t2].reverse = reverse;
794 colliders[t2][t1].fn = fn;
795 colliders[t2][t1].reverse = !reverse;
796
797 // now call the collider function indirectly through dCollide(), so that
798 // contact reversing is properly handled.
799 return dCollide (o1,o2,flags,contact,skip);
800}
801
802
803int dCreateGeomClass (const dGeomClass *c)
804{
805 dUASSERT(c && c->bytes >= 0 && c->collider && c->aabb,"bad geom class");
806
807 if (num_user_classes >= dMaxUserClasses) {
808 dDebug (0,"too many user classes, you must increase the limit and "
809 "recompile ODE");
810 }
811 user_classes[num_user_classes] = *c;
812 int class_number = num_user_classes + dFirstUserClass;
813 initColliders();
814 setAllColliders (class_number,&dCollideUserGeomWithGeom);
815
816 num_user_classes++;
817 return class_number;
818}
819
820
821void * dGeomGetClassData (dxGeom *g)
822{
823 dUASSERT (g && g->type >= dFirstUserClass &&
824 g->type <= dLastUserClass,"not a custom class");
825 dxUserGeom *user = (dxUserGeom*) g;
826 return user->user_data;
827}
828
829
830dGeomID dCreateGeom (int classnum)
831{
832 dUASSERT (classnum >= dFirstUserClass &&
833 classnum <= dLastUserClass,"not a custom class");
834 return new dxUserGeom (classnum);
835}
836
837
838
839/* ************************************************************************ */
840/* geom offset from body */
841
842void dGeomCreateOffset (dxGeom *g)
843{
844 dAASSERT (g);
845 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
846 dUASSERT (g->body, "geom must be on a body");
847 if (g->offset_posr)
848 {
849 return; // already created
850 }
851 dIASSERT (g->final_posr == &g->body->posr);
852
853 g->final_posr = dAllocPosr();
854 g->offset_posr = dAllocPosr();
855 dSetZero (g->offset_posr->pos,4);
856 dRSetIdentity (g->offset_posr->R);
857
858 g->gflags |= GEOM_POSR_BAD;
859}
860
861void dGeomSetOffsetPosition (dxGeom *g, dReal x, dReal y, dReal z)
862{
863 dAASSERT (g);
864 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
865 dUASSERT (g->body, "geom must be on a body");
866 CHECK_NOT_LOCKED (g->parent_space);
867 if (!g->offset_posr)
868 {
869 dGeomCreateOffset(g);
870 }
871 g->offset_posr->pos[0] = x;
872 g->offset_posr->pos[1] = y;
873 g->offset_posr->pos[2] = z;
874 dGeomMoved (g);
875}
876
877void dGeomSetOffsetRotation (dxGeom *g, const dMatrix3 R)
878{
879 dAASSERT (g && R);
880 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
881 dUASSERT (g->body, "geom must be on a body");
882 CHECK_NOT_LOCKED (g->parent_space);
883 if (!g->offset_posr)
884 {
885 dGeomCreateOffset (g);
886 }
887 memcpy (g->offset_posr->R,R,sizeof(dMatrix3));
888 dGeomMoved (g);
889}
890
891void dGeomSetOffsetQuaternion (dxGeom *g, const dQuaternion quat)
892{
893 dAASSERT (g && quat);
894 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
895 dUASSERT (g->body, "geom must be on a body");
896 CHECK_NOT_LOCKED (g->parent_space);
897 if (!g->offset_posr)
898 {
899 dGeomCreateOffset (g);
900 }
901 dQtoR (quat, g->offset_posr->R);
902 dGeomMoved (g);
903}
904
905void dGeomSetOffsetWorldPosition (dxGeom *g, dReal x, dReal y, dReal z)
906{
907 dAASSERT (g);
908 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
909 dUASSERT (g->body, "geom must be on a body");
910 CHECK_NOT_LOCKED (g->parent_space);
911 if (!g->offset_posr)
912 {
913 dGeomCreateOffset(g);
914 }
915 dBodyGetPosRelPoint(g->body, x, y, z, g->offset_posr->pos);
916 dGeomMoved (g);
917}
918
919void dGeomSetOffsetWorldRotation (dxGeom *g, const dMatrix3 R)
920{
921 dAASSERT (g && R);
922 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
923 dUASSERT (g->body, "geom must be on a body");
924 CHECK_NOT_LOCKED (g->parent_space);
925 if (!g->offset_posr)
926 {
927 dGeomCreateOffset (g);
928 }
929 g->recomputePosr();
930
931 dxPosR new_final_posr;
932 memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
933 memcpy(new_final_posr.R, R, sizeof(dMatrix3));
934
935 getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr);
936 dGeomMoved (g);
937}
938
939void dGeomSetOffsetWorldQuaternion (dxGeom *g, const dQuaternion quat)
940{
941 dAASSERT (g && quat);
942 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
943 dUASSERT (g->body, "geom must be on a body");
944 CHECK_NOT_LOCKED (g->parent_space);
945 if (!g->offset_posr)
946 {
947 dGeomCreateOffset (g);
948 }
949
950 g->recomputePosr();
951
952 dxPosR new_final_posr;
953 memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
954 dQtoR (quat, new_final_posr.R);
955
956 getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr);
957 dGeomMoved (g);
958}
959
960void dGeomClearOffset(dxGeom *g)
961{
962 dAASSERT (g);
963 dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
964 if (g->offset_posr)
965 {
966 dIASSERT(g->body);
967 // no longer need an offset posr
968 dFreePosr(g->offset_posr);
969 g->offset_posr = 0;
970 // the geom will now share the position of the body
971 dFreePosr(g->final_posr);
972 g->final_posr = &g->body->posr;
973 // geom has moved
974 g->gflags &= ~GEOM_POSR_BAD;
975 dGeomMoved (g);
976 }
977}
978
979int dGeomIsOffset(dxGeom *g)
980{
981 dAASSERT (g);
982 return ((0 != g->offset_posr) ? 1 : 0);
983}
984
985static const dVector3 OFFSET_POSITION_ZERO = { 0.0f, 0.0f, 0.0f, 0.0f };
986
987const dReal * dGeomGetOffsetPosition (dxGeom *g)
988{
989 dAASSERT (g);
990 if (g->offset_posr)
991 {
992 return g->offset_posr->pos;
993 }
994 return OFFSET_POSITION_ZERO;
995}
996
997void dGeomCopyOffsetPosition (dxGeom *g, dVector3 pos)
998{
999 dAASSERT (g);
1000 if (g->offset_posr)
1001 {
1002 const dReal* src = g->offset_posr->pos;
1003 pos[0] = src[0];
1004 pos[1] = src[1];
1005 pos[2] = src[2];
1006 }
1007 else
1008 {
1009 pos[0] = 0;
1010 pos[1] = 0;
1011 pos[2] = 0;
1012 }
1013}
1014
1015static const dMatrix3 OFFSET_ROTATION_ZERO =
1016{
1017 1.0f, 0.0f, 0.0f, 0.0f,
1018 0.0f, 1.0f, 0.0f, 0.0f,
1019 0.0f, 0.0f, 1.0f, 0.0f,
1020};
1021
1022const dReal * dGeomGetOffsetRotation (dxGeom *g)
1023{
1024 dAASSERT (g);
1025 if (g->offset_posr)
1026 {
1027 return g->offset_posr->R;
1028 }
1029 return OFFSET_ROTATION_ZERO;
1030}
1031
1032void dGeomCopyOffsetRotation (dxGeom *g, dMatrix3 R)
1033{
1034 dAASSERT (g);
1035 if (g->offset_posr)
1036 {
1037 const dReal* src = g->final_posr->R;
1038 R[0] = src[0];
1039 R[1] = src[1];
1040 R[2] = src[2];
1041 R[4] = src[4];
1042 R[5] = src[5];
1043 R[6] = src[6];
1044 R[8] = src[8];
1045 R[9] = src[9];
1046 R[10] = src[10];
1047 }
1048 else
1049 {
1050 R[0] = OFFSET_ROTATION_ZERO[0];
1051 R[1] = OFFSET_ROTATION_ZERO[1];
1052 R[2] = OFFSET_ROTATION_ZERO[2];
1053 R[4] = OFFSET_ROTATION_ZERO[4];
1054 R[5] = OFFSET_ROTATION_ZERO[5];
1055 R[6] = OFFSET_ROTATION_ZERO[6];
1056 R[8] = OFFSET_ROTATION_ZERO[8];
1057 R[9] = OFFSET_ROTATION_ZERO[9];
1058 R[10] = OFFSET_ROTATION_ZERO[10];
1059 }
1060}
1061
1062void dGeomGetOffsetQuaternion (dxGeom *g, dQuaternion result)
1063{
1064 dAASSERT (g);
1065 if (g->offset_posr)
1066 {
1067 dRtoQ (g->offset_posr->R, result);
1068 }
1069 else
1070 {
1071 dSetZero (result,4);
1072 result[0] = 1;
1073 }
1074}
1075
1076//****************************************************************************
1077// initialization and shutdown routines - allocate and initialize data,
1078// cleanup before exiting
1079
1080extern void opcode_collider_cleanup();
1081
1082void dInitODE()
1083{
1084#if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
1085 gimpact_init();
1086#endif
1087}
1088
1089void dCloseODE()
1090{
1091 colliders_initialized = 0;
1092 num_user_classes = 0;
1093 dClearPosrCache();
1094
1095#if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
1096 gimpact_terminate();
1097#endif
1098
1099#if dTRIMESH_ENABLED && dTRIMESH_OPCODE
1100 // Free up static allocations in opcode
1101 opcode_collider_cleanup();
1102#endif
1103}
diff --git a/libraries/ode-0.9/ode/src/collision_kernel.h b/libraries/ode-0.9/ode/src/collision_kernel.h
deleted file mode 100644
index d5a2bc4..0000000
--- a/libraries/ode-0.9/ode/src/collision_kernel.h
+++ /dev/null
@@ -1,214 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25internal data structures and functions for collision detection.
26
27*/
28
29#ifndef _ODE_COLLISION_KERNEL_H_
30#define _ODE_COLLISION_KERNEL_H_
31
32#include <ode/common.h>
33#include <ode/contact.h>
34#include <ode/collision.h>
35#include "objects.h"
36
37//****************************************************************************
38// constants and macros
39
40// mask for the number-of-contacts field in the dCollide() flags parameter
41#define NUMC_MASK (0xffff)
42
43#define IS_SPACE(geom) \
44 ((geom)->type >= dFirstSpaceClass && (geom)->type <= dLastSpaceClass)
45
46//****************************************************************************
47// geometry object base class
48
49
50// geom flags.
51//
52// GEOM_DIRTY means that the space data structures for this geom are
53// potentially not up to date. NOTE THAT all space parents of a dirty geom
54// are themselves dirty. this is an invariant that must be enforced.
55//
56// GEOM_AABB_BAD means that the cached AABB for this geom is not up to date.
57// note that GEOM_DIRTY does not imply GEOM_AABB_BAD, as the geom might
58// recalculate its own AABB but does not know how to update the space data
59// structures for the space it is in. but GEOM_AABB_BAD implies GEOM_DIRTY.
60// the valid combinations are:
61// 0
62// GEOM_DIRTY
63// GEOM_DIRTY|GEOM_AABB_BAD
64// GEOM_DIRTY|GEOM_AABB_BAD|GEOM_POSR_BAD
65
66enum {
67 GEOM_DIRTY = 1, // geom is 'dirty', i.e. position unknown
68 GEOM_POSR_BAD = 2, // geom's final posr is not valid
69 GEOM_AABB_BAD = 4, // geom's AABB is not valid
70 GEOM_PLACEABLE = 8, // geom is placeable
71 GEOM_ENABLED = 16, // geom is enabled
72
73 // Ray specific
74 RAY_FIRSTCONTACT = 0x10000,
75 RAY_BACKFACECULL = 0x20000,
76 RAY_CLOSEST_HIT = 0x40000
77};
78
79
80// geometry object base class. pos and R will either point to a separately
81// allocated buffer (if body is 0 - pos points to the dxPosR object) or to
82// the pos and R of the body (if body nonzero).
83// a dGeomID is a pointer to this object.
84
85struct dxGeom : public dBase {
86 int type; // geom type number, set by subclass constructor
87 int gflags; // flags used by geom and space
88 void *data; // user-defined data pointer
89 dBodyID body; // dynamics body associated with this object (if any)
90 dxGeom *body_next; // next geom in body's linked list of associated geoms
91 dxPosR *final_posr; // final position of the geom in world coordinates
92 dxPosR *offset_posr; // offset from body in local coordinates
93
94 // information used by spaces
95 dxGeom *next; // next geom in linked list of geoms
96 dxGeom **tome; // linked list backpointer
97 dxSpace *parent_space;// the space this geom is contained in, 0 if none
98 dReal aabb[6]; // cached AABB for this space
99 unsigned long category_bits,collide_bits;
100
101 dxGeom (dSpaceID _space, int is_placeable);
102 virtual ~dxGeom();
103
104
105 // calculate our new final position from our offset and body
106 void computePosr();
107
108 // recalculate our new final position if needed
109 void recomputePosr()
110 {
111 if (gflags & GEOM_POSR_BAD) {
112 computePosr();
113 gflags &= ~GEOM_POSR_BAD;
114 }
115 }
116
117 virtual void computeAABB()=0;
118 // compute the AABB for this object and put it in aabb. this function
119 // always performs a fresh computation, it does not inspect the
120 // GEOM_AABB_BAD flag.
121
122 virtual int AABBTest (dxGeom *o, dReal aabb[6]);
123 // test whether the given AABB object intersects with this object, return
124 // 1=yes, 0=no. this is used as an early-exit test in the space collision
125 // functions. the default implementation returns 1, which is the correct
126 // behavior if no more detailed implementation can be provided.
127
128 // utility functions
129
130 // compute the AABB only if it is not current. this function manipulates
131 // the GEOM_AABB_BAD flag.
132
133 void recomputeAABB() {
134 if (gflags & GEOM_AABB_BAD) {
135 // our aabb functions assume final_posr is up to date
136 recomputePosr();
137 computeAABB();
138 gflags &= ~GEOM_AABB_BAD;
139 }
140 }
141
142 // add and remove this geom from a linked list maintained by a space.
143
144 void spaceAdd (dxGeom **first_ptr) {
145 next = *first_ptr;
146 tome = first_ptr;
147 if (*first_ptr) (*first_ptr)->tome = &next;
148 *first_ptr = this;
149 }
150 void spaceRemove() {
151 if (next) next->tome = tome;
152 *tome = next;
153 }
154
155 // add and remove this geom from a linked list maintained by a body.
156
157 void bodyAdd (dxBody *b) {
158 body = b;
159 body_next = b->geom;
160 b->geom = this;
161 }
162 void bodyRemove();
163};
164
165//****************************************************************************
166// the base space class
167//
168// the contained geoms are divided into two kinds: clean and dirty.
169// the clean geoms have not moved since they were put in the list,
170// and their AABBs are valid. the dirty geoms have changed position, and
171// their AABBs are may not be valid. the two types are distinguished by the
172// GEOM_DIRTY flag. all dirty geoms come *before* all clean geoms in the list.
173
174struct dxSpace : public dxGeom {
175 int count; // number of geoms in this space
176 dxGeom *first; // first geom in list
177 int cleanup; // cleanup mode, 1=destroy geoms on exit
178
179 // cached state for getGeom()
180 int current_index; // only valid if current_geom != 0
181 dxGeom *current_geom; // if 0 then there is no information
182
183 // locking stuff. the space is locked when it is currently traversing its
184 // internal data structures, e.g. in collide() and collide2(). operations
185 // that modify the contents of the space are not permitted when the space
186 // is locked.
187 int lock_count;
188
189 dxSpace (dSpaceID _space);
190 ~dxSpace();
191
192 void computeAABB();
193
194 void setCleanup (int mode);
195 int getCleanup();
196 int query (dxGeom *geom);
197 int getNumGeoms();
198 virtual dxGeom *getGeom (int i);
199
200 virtual void add (dxGeom *);
201 virtual void remove (dxGeom *);
202 virtual void dirty (dxGeom *);
203
204 virtual void cleanGeoms()=0;
205 // turn all dirty geoms into clean geoms by computing their AABBs and any
206 // other space data structures that are required. this should clear the
207 // GEOM_DIRTY and GEOM_AABB_BAD flags of all geoms.
208
209 virtual void collide (void *data, dNearCallback *callback)=0;
210 virtual void collide2 (void *data, dxGeom *geom, dNearCallback *callback)=0;
211};
212
213
214#endif
diff --git a/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp b/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp
deleted file mode 100644
index 86a1833..0000000
--- a/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp
+++ /dev/null
@@ -1,584 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// QuadTreeSpace by Erwin de Vries.
24
25#include <ode/common.h>
26#include <ode/matrix.h>
27#include <ode/collision_space.h>
28#include <ode/collision.h>
29#include "collision_kernel.h"
30
31#include "collision_space_internal.h"
32
33
34#define AXIS0 0
35#define AXIS1 1
36#define UP 2
37
38//#define DRAWBLOCKS
39
40const int SPLITAXIS = 2;
41const int SPLITS = SPLITAXIS * SPLITAXIS;
42
43#define GEOM_ENABLED(g) (g)->gflags & GEOM_ENABLED
44
45class Block{
46public:
47 dReal MinX, MaxX;
48 dReal MinZ, MaxZ;
49
50 dGeomID First;
51 int GeomCount;
52
53 Block* Parent;
54 Block* Children;
55
56 void Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks);
57
58 void Collide(void* UserData, dNearCallback* Callback);
59 void Collide(dGeomID Object, dGeomID g, void* UserData, dNearCallback* Callback);
60
61 void CollideLocal(dGeomID Object, void* UserData, dNearCallback* Callback);
62
63 void AddObject(dGeomID Object);
64 void DelObject(dGeomID Object);
65 void Traverse(dGeomID Object);
66
67 bool Inside(const dReal* AABB);
68
69 Block* GetBlock(const dReal* AABB);
70 Block* GetBlockChild(const dReal* AABB);
71};
72
73
74#ifdef DRAWBLOCKS
75#include "..\..\Include\drawstuff\\drawstuff.h"
76
77static void DrawBlock(Block* Block){
78 dVector3 v[8];
79 v[0][AXIS0] = Block->MinX;
80 v[0][UP] = REAL(-1.0);
81 v[0][AXIS1] = Block->MinZ;
82
83 v[1][AXIS0] = Block->MinX;
84 v[1][UP] = REAL(-1.0);
85 v[1][AXIS1] = Block->MaxZ;
86
87 v[2][AXIS0] = Block->MaxX;
88 v[2][UP] = REAL(-1.0);
89 v[2][AXIS1] = Block->MinZ;
90
91 v[3][AXIS0] = Block->MaxX;
92 v[3][UP] = REAL(-1.0);
93 v[3][AXIS1] = Block->MaxZ;
94
95 v[4][AXIS0] = Block->MinX;
96 v[4][UP] = REAL(1.0);
97 v[4][AXIS1] = Block->MinZ;
98
99 v[5][AXIS0] = Block->MinX;
100 v[5][UP] = REAL(1.0);
101 v[5][AXIS1] = Block->MaxZ;
102
103 v[6][AXIS0] = Block->MaxX;
104 v[6][UP] = REAL(1.0);
105 v[6][AXIS1] = Block->MinZ;
106
107 v[7][AXIS0] = Block->MaxX;
108 v[7][UP] = REAL(1.0);
109 v[7][AXIS1] = Block->MaxZ;
110
111 // Bottom
112 dsDrawLine(v[0], v[1]);
113 dsDrawLine(v[1], v[3]);
114 dsDrawLine(v[3], v[2]);
115 dsDrawLine(v[2], v[0]);
116
117 // Top
118 dsDrawLine(v[4], v[5]);
119 dsDrawLine(v[5], v[7]);
120 dsDrawLine(v[7], v[6]);
121 dsDrawLine(v[6], v[4]);
122
123 // Sides
124 dsDrawLine(v[0], v[4]);
125 dsDrawLine(v[1], v[5]);
126 dsDrawLine(v[2], v[6]);
127 dsDrawLine(v[3], v[7]);
128}
129#endif //DRAWBLOCKS
130
131
132void Block::Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks){
133 GeomCount = 0;
134 First = 0;
135
136 MinX = Center[AXIS0] - Extents[AXIS0];
137 MaxX = Center[AXIS0] + Extents[AXIS0];
138
139 MinZ = Center[AXIS1] - Extents[AXIS1];
140 MaxZ = Center[AXIS1] + Extents[AXIS1];
141
142 this->Parent = Parent;
143 if (Depth > 0){
144 Children = Blocks;
145 Blocks += SPLITS;
146
147 dVector3 ChildExtents;
148 ChildExtents[AXIS0] = Extents[AXIS0] / SPLITAXIS;
149 ChildExtents[AXIS1] = Extents[AXIS1] / SPLITAXIS;
150 ChildExtents[UP] = Extents[UP];
151
152 for (int i = 0; i < SPLITAXIS; i++){
153 for (int j = 0; j < SPLITAXIS; j++){
154 int Index = i * SPLITAXIS + j;
155
156 dVector3 ChildCenter;
157 ChildCenter[AXIS0] = Center[AXIS0] - Extents[AXIS0] + ChildExtents[AXIS0] + i * (ChildExtents[AXIS0] * 2);
158 ChildCenter[AXIS1] = Center[AXIS1] - Extents[AXIS1] + ChildExtents[AXIS1] + j * (ChildExtents[AXIS1] * 2);
159 ChildCenter[UP] = Center[UP];
160
161 Children[Index].Create(ChildCenter, ChildExtents, this, Depth - 1, Blocks);
162 }
163 }
164 }
165 else Children = 0;
166}
167
168void Block::Collide(void* UserData, dNearCallback* Callback){
169#ifdef DRAWBLOCKS
170 DrawBlock(this);
171#endif
172 // Collide the local list
173 dxGeom* g = First;
174 while (g){
175 if (GEOM_ENABLED(g)){
176 Collide(g, g->next, UserData, Callback);
177 }
178 g = g->next;
179 }
180
181 // Recurse for children
182 if (Children){
183 for (int i = 0; i < SPLITS; i++){
184 if (Children[i].GeomCount <= 1){ // Early out
185 continue;
186 }
187 Children[i].Collide(UserData, Callback);
188 }
189 }
190}
191
192void Block::Collide(dxGeom* g1, dxGeom* g2, void* UserData, dNearCallback* Callback){
193#ifdef DRAWBLOCKS
194 DrawBlock(this);
195#endif
196 // Collide against local list
197 while (g2){
198 if (GEOM_ENABLED(g2)){
199 collideAABBs (g1, g2, UserData, Callback);
200 }
201 g2 = g2->next;
202 }
203
204 // Collide against children
205 if (Children){
206 for (int i = 0; i < SPLITS; i++){
207 // Early out for empty blocks
208 if (Children[i].GeomCount == 0){
209 continue;
210 }
211
212 // Does the geom's AABB collide with the block?
213 // Dont do AABB tests for single geom blocks.
214 if (Children[i].GeomCount == 1 && Children[i].First){
215 //
216 }
217 else if (true){
218 if (g1->aabb[AXIS0 * 2 + 0] > Children[i].MaxX ||
219 g1->aabb[AXIS0 * 2 + 1] < Children[i].MinX ||
220 g1->aabb[AXIS1 * 2 + 0] > Children[i].MaxZ ||
221 g1->aabb[AXIS1 * 2 + 1] < Children[i].MinZ) continue;
222 }
223 Children[i].Collide(g1, Children[i].First, UserData, Callback);
224 }
225 }
226}
227
228void Block::CollideLocal(dxGeom* g1, void* UserData, dNearCallback* Callback){
229 // Collide against local list
230 dxGeom* g2 = First;
231 while (g2){
232 if (GEOM_ENABLED(g2)){
233 collideAABBs (g1, g2, UserData, Callback);
234 }
235 g2 = g2->next;
236 }
237}
238
239void Block::AddObject(dGeomID Object){
240 // Add the geom
241 Object->next = First;
242 First = Object;
243 Object->tome = (dxGeom**)this;
244
245 // Now traverse upwards to tell that we have a geom
246 Block* Block = this;
247 do{
248 Block->GeomCount++;
249 Block = Block->Parent;
250 }
251 while (Block);
252}
253
254void Block::DelObject(dGeomID Object){
255 // Del the geom
256 dxGeom* g = First;
257 dxGeom* Last = 0;
258 while (g){
259 if (g == Object){
260 if (Last){
261 Last->next = g->next;
262 }
263 else First = g->next;
264
265 break;
266 }
267 Last = g;
268 g = g->next;
269 }
270
271 Object->tome = 0;
272
273 // Now traverse upwards to tell that we have lost a geom
274 Block* Block = this;
275 do{
276 Block->GeomCount--;
277 Block = Block->Parent;
278 }
279 while (Block);
280}
281
282void Block::Traverse(dGeomID Object){
283 Block* NewBlock = GetBlock(Object->aabb);
284
285 if (NewBlock != this){
286 // Remove the geom from the old block and add it to the new block.
287 // This could be more optimal, but the loss should be very small.
288 DelObject(Object);
289 NewBlock->AddObject(Object);
290 }
291}
292
293bool Block::Inside(const dReal* AABB){
294 return AABB[AXIS0 * 2 + 0] >= MinX && AABB[AXIS0 * 2 + 1] <= MaxX && AABB[AXIS1 * 2 + 0] >= MinZ && AABB[AXIS1 * 2 + 1] <= MaxZ;
295}
296
297Block* Block::GetBlock(const dReal* AABB){
298 if (Inside(AABB)){
299 return GetBlockChild(AABB); // Child or this will have a good block
300 }
301 else if (Parent){
302 return Parent->GetBlock(AABB); // Parent has a good block
303 }
304 else return this; // We are at the root, so we have little choice
305}
306
307Block* Block::GetBlockChild(const dReal* AABB){
308 if (Children){
309 for (int i = 0; i < SPLITS; i++){
310 if (Children[i].Inside(AABB)){
311 return Children[i].GetBlockChild(AABB); // Child will have good block
312 }
313 }
314 }
315 return this; // This is the best block
316}
317
318//****************************************************************************
319// quadtree space
320
321struct dxQuadTreeSpace : public dxSpace{
322 Block* Blocks; // Blocks[0] is the root
323
324 dArray<dxGeom*> DirtyList;
325
326 dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth);
327 ~dxQuadTreeSpace();
328
329 dxGeom* getGeom(int i);
330
331 void add(dxGeom* g);
332 void remove(dxGeom* g);
333 void dirty(dxGeom* g);
334
335 void computeAABB();
336
337 void cleanGeoms();
338 void collide(void* UserData, dNearCallback* Callback);
339 void collide2(void* UserData, dxGeom* g1, dNearCallback* Callback);
340
341 // Temp data
342 Block* CurrentBlock; // Only used while enumerating
343 int* CurrentChild; // Only used while enumerating
344 int CurrentLevel; // Only used while enumerating
345 dxGeom* CurrentObject; // Only used while enumerating
346 int CurrentIndex;
347};
348
349dxQuadTreeSpace::dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth) : dxSpace(_space){
350 type = dQuadTreeSpaceClass;
351
352 int BlockCount = 0;
353 for (int i = 0; i <= Depth; i++){
354 BlockCount += (int)pow((dReal)SPLITS, i);
355 }
356
357 Blocks = (Block*)dAlloc(BlockCount * sizeof(Block));
358 Block* Blocks = this->Blocks + 1; // This pointer gets modified!
359
360 this->Blocks[0].Create(Center, Extents, 0, Depth, Blocks);
361
362 CurrentBlock = 0;
363 CurrentChild = (int*)dAlloc((Depth + 1) * sizeof(int));
364 CurrentLevel = 0;
365 CurrentObject = 0;
366 CurrentIndex = -1;
367
368 // 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
369 aabb[0] = -dInfinity;
370 aabb[1] = dInfinity;
371 aabb[2] = -dInfinity;
372 aabb[3] = dInfinity;
373 aabb[4] = -dInfinity;
374 aabb[5] = dInfinity;
375}
376
377dxQuadTreeSpace::~dxQuadTreeSpace(){
378 int Depth = 0;
379 Block* Current = &Blocks[0];
380 while (Current){
381 Depth++;
382 Current = Current->Children;
383 }
384
385 int BlockCount = 0;
386 for (int i = 0; i < Depth; i++){
387 BlockCount += (int)pow((dReal)SPLITS, i);
388 }
389
390 dFree(Blocks, BlockCount * sizeof(Block));
391 dFree(CurrentChild, (Depth + 1) * sizeof(int));
392}
393
394dxGeom* dxQuadTreeSpace::getGeom(int Index){
395 dUASSERT(Index >= 0 && Index < count, "index out of range");
396
397 //@@@
398 dDebug (0,"dxQuadTreeSpace::getGeom() not yet implemented");
399
400 return 0;
401
402 // This doesnt work
403
404 /*if (CurrentIndex == Index){
405 // Loop through all objects in the local list
406CHILDRECURSE:
407 if (CurrentObject){
408 dGeomID g = CurrentObject;
409 CurrentObject = CurrentObject->next;
410 CurrentIndex++;
411
412#ifdef DRAWBLOCKS
413 DrawBlock(CurrentBlock);
414#endif //DRAWBLOCKS
415 return g;
416 }
417 else{
418 // Now lets loop through our children. Starting at index 0.
419 if (CurrentBlock->Children){
420 CurrentChild[CurrentLevel] = 0;
421PARENTRECURSE:
422 for (int& i = CurrentChild[CurrentLevel]; i < SPLITS; i++){
423 if (CurrentBlock->Children[i].GeomCount == 0){
424 continue;
425 }
426 CurrentBlock = &CurrentBlock->Children[i];
427 CurrentObject = CurrentBlock->First;
428
429 i++;
430
431 CurrentLevel++;
432 goto CHILDRECURSE;
433 }
434 }
435 }
436
437 // Now lets go back to the parent so it can continue processing its other children.
438 if (CurrentBlock->Parent){
439 CurrentBlock = CurrentBlock->Parent;
440 CurrentLevel--;
441 goto PARENTRECURSE;
442 }
443 }
444 else{
445 CurrentBlock = &Blocks[0];
446 CurrentLevel = 0;
447 CurrentObject = CurrentObject;
448 CurrentIndex = 0;
449
450 // Other states are already set
451 CurrentObject = CurrentBlock->First;
452 }
453
454
455 if (current_geom && current_index == Index - 1){
456 //current_geom = current_geom->next; // next
457 current_index = Index;
458 return current_geom;
459 }
460 else for (int i = 0; i < Index; i++){ // this will be verrrrrrry slow
461 getGeom(i);
462 }*/
463
464 return 0;
465}
466
467void dxQuadTreeSpace::add(dxGeom* g){
468 CHECK_NOT_LOCKED (this);
469 dAASSERT(g);
470 dUASSERT(g->parent_space == 0 && g->next == 0, "geom is already in a space");
471
472 g->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
473 DirtyList.push(g);
474
475 // add
476 g->parent_space = this;
477 Blocks[0].GetBlock(g->aabb)->AddObject(g); // Add to best block
478 count++;
479
480 // enumerator has been invalidated
481 current_geom = 0;
482
483 dGeomMoved(this);
484}
485
486void dxQuadTreeSpace::remove(dxGeom* g){
487 CHECK_NOT_LOCKED(this);
488 dAASSERT(g);
489 dUASSERT(g->parent_space == this,"object is not in this space");
490
491 // remove
492 ((Block*)g->tome)->DelObject(g);
493 count--;
494
495 for (int i = 0; i < DirtyList.size(); i++){
496 if (DirtyList[i] == g){
497 DirtyList.remove(i);
498 // (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
499 --i;
500 }
501 }
502
503 // safeguard
504 g->next = 0;
505 g->tome = 0;
506 g->parent_space = 0;
507
508 // enumerator has been invalidated
509 current_geom = 0;
510
511 // the bounding box of this space (and that of all the parents) may have
512 // changed as a consequence of the removal.
513 dGeomMoved(this);
514}
515
516void dxQuadTreeSpace::dirty(dxGeom* g){
517 DirtyList.push(g);
518}
519
520void dxQuadTreeSpace::computeAABB(){
521 //
522}
523
524void dxQuadTreeSpace::cleanGeoms(){
525 // compute the AABBs of all dirty geoms, and clear the dirty flags
526 lock_count++;
527
528 for (int i = 0; i < DirtyList.size(); i++){
529 dxGeom* g = DirtyList[i];
530 if (IS_SPACE(g)){
531 ((dxSpace*)g)->cleanGeoms();
532 }
533 g->recomputeAABB();
534 g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
535
536 ((Block*)g->tome)->Traverse(g);
537 }
538 DirtyList.setSize(0);
539
540 lock_count--;
541}
542
543void dxQuadTreeSpace::collide(void* UserData, dNearCallback* Callback){
544 dAASSERT(Callback);
545
546 lock_count++;
547 cleanGeoms();
548
549 Blocks[0].Collide(UserData, Callback);
550
551 lock_count--;
552}
553
554void dxQuadTreeSpace::collide2(void* UserData, dxGeom* g1, dNearCallback* Callback){
555 dAASSERT(g1 && Callback);
556
557 lock_count++;
558 cleanGeoms();
559 g1->recomputeAABB();
560
561 if (g1->parent_space == this){
562 // The block the geom is in
563 Block* CurrentBlock = (Block*)g1->tome;
564
565 // Collide against block and its children
566 CurrentBlock->Collide(g1, CurrentBlock->First, UserData, Callback);
567
568 // Collide against parents
569 while (true){
570 CurrentBlock = CurrentBlock->Parent;
571 if (!CurrentBlock){
572 break;
573 }
574 CurrentBlock->CollideLocal(g1, UserData, Callback);
575 }
576 }
577 else Blocks[0].Collide(g1, Blocks[0].First, UserData, Callback);
578
579 lock_count--;
580}
581
582dSpaceID dQuadTreeSpaceCreate(dxSpace* space, dVector3 Center, dVector3 Extents, int Depth){
583 return new dxQuadTreeSpace(space, Center, Extents, Depth);
584}
diff --git a/libraries/ode-0.9/ode/src/collision_space.cpp b/libraries/ode-0.9/ode/src/collision_space.cpp
deleted file mode 100644
index 1a8fc81..0000000
--- a/libraries/ode-0.9/ode/src/collision_space.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25spaces
26
27*/
28
29#include <ode/common.h>
30#include <ode/matrix.h>
31#include <ode/collision_space.h>
32#include <ode/collision.h>
33#include "collision_kernel.h"
34
35#include "collision_space_internal.h"
36
37#ifdef _MSC_VER
38#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
39#endif
40
41//****************************************************************************
42// make the geom dirty by setting the GEOM_DIRTY and GEOM_BAD_AABB flags
43// and moving it to the front of the space's list. all the parents of a
44// dirty geom also become dirty.
45
46void dGeomMoved (dxGeom *geom)
47{
48 dAASSERT (geom);
49
50 // if geom is offset, mark it as needing a calculate
51 if (geom->offset_posr) {
52 geom->gflags |= GEOM_POSR_BAD;
53 }
54
55 // from the bottom of the space heirarchy up, process all clean geoms
56 // turning them into dirty geoms.
57 dxSpace *parent = geom->parent_space;
58
59 while (parent && (geom->gflags & GEOM_DIRTY)==0) {
60 CHECK_NOT_LOCKED (parent);
61 geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
62 parent->dirty (geom);
63 geom = parent;
64 parent = parent->parent_space;
65 }
66
67 // all the remaining dirty geoms must have their AABB_BAD flags set, to
68 // ensure that their AABBs get recomputed
69 while (geom) {
70 geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
71 CHECK_NOT_LOCKED (geom->parent_space);
72 geom = geom->parent_space;
73 }
74}
75
76#define GEOM_ENABLED(g) ((g)->gflags & GEOM_ENABLED)
77
78//****************************************************************************
79// dxSpace
80
81dxSpace::dxSpace (dSpaceID _space) : dxGeom (_space,0)
82{
83 count = 0;
84 first = 0;
85 cleanup = 1;
86 current_index = 0;
87 current_geom = 0;
88 lock_count = 0;
89}
90
91
92dxSpace::~dxSpace()
93{
94 CHECK_NOT_LOCKED (this);
95 if (cleanup) {
96 // note that destroying each geom will call remove()
97 dxGeom *g,*n;
98 for (g = first; g; g=n) {
99 n = g->next;
100 dGeomDestroy (g);
101 }
102 }
103 else {
104 dxGeom *g,*n;
105 for (g = first; g; g=n) {
106 n = g->next;
107 remove (g);
108 }
109 }
110}
111
112
113void dxSpace::computeAABB()
114{
115 if (first) {
116 int i;
117 dReal a[6];
118 a[0] = dInfinity;
119 a[1] = -dInfinity;
120 a[2] = dInfinity;
121 a[3] = -dInfinity;
122 a[4] = dInfinity;
123 a[5] = -dInfinity;
124 for (dxGeom *g=first; g; g=g->next) {
125 g->recomputeAABB();
126 for (i=0; i<6; i += 2) if (g->aabb[i] < a[i]) a[i] = g->aabb[i];
127 for (i=1; i<6; i += 2) if (g->aabb[i] > a[i]) a[i] = g->aabb[i];
128 }
129 memcpy(aabb,a,6*sizeof(dReal));
130 }
131 else {
132 dSetZero (aabb,6);
133 }
134}
135
136
137void dxSpace::setCleanup (int mode)
138{
139 cleanup = (mode != 0);
140}
141
142
143int dxSpace::getCleanup()
144{
145 return cleanup;
146}
147
148
149int dxSpace::query (dxGeom *geom)
150{
151 dAASSERT (geom);
152 return (geom->parent_space == this);
153}
154
155
156int dxSpace::getNumGeoms()
157{
158 return count;
159}
160
161
162// the dirty geoms are numbered 0..k, the clean geoms are numbered k+1..count-1
163
164dxGeom *dxSpace::getGeom (int i)
165{
166 dUASSERT (i >= 0 && i < count,"index out of range");
167 if (current_geom && current_index == i-1) {
168 current_geom = current_geom->next;
169 current_index = i;
170 return current_geom;
171 }
172 else {
173 dxGeom *g=first;
174 for (int j=0; j<i; j++) {
175 if (g) g = g->next; else return 0;
176 }
177 current_geom = g;
178 current_index = i;
179 return g;
180 }
181}
182
183
184void dxSpace::add (dxGeom *geom)
185{
186 CHECK_NOT_LOCKED (this);
187 dAASSERT (geom);
188 dUASSERT (geom->parent_space == 0 && geom->next == 0,
189 "geom is already in a space");
190
191 // add
192 geom->parent_space = this;
193 geom->spaceAdd (&first);
194 count++;
195
196 // enumerator has been invalidated
197 current_geom = 0;
198
199 // new geoms are added to the front of the list and are always
200 // considered to be dirty. as a consequence, this space and all its
201 // parents are dirty too.
202 geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
203 dGeomMoved (this);
204}
205
206
207void dxSpace::remove (dxGeom *geom)
208{
209 CHECK_NOT_LOCKED (this);
210 dAASSERT (geom);
211 dUASSERT (geom->parent_space == this,"object is not in this space");
212
213 // remove
214 geom->spaceRemove();
215 count--;
216
217 // safeguard
218 geom->next = 0;
219 geom->tome = 0;
220 geom->parent_space = 0;
221
222 // enumerator has been invalidated
223 current_geom = 0;
224
225 // the bounding box of this space (and that of all the parents) may have
226 // changed as a consequence of the removal.
227 dGeomMoved (this);
228}
229
230
231void dxSpace::dirty (dxGeom *geom)
232{
233 geom->spaceRemove();
234 geom->spaceAdd (&first);
235}
236
237//****************************************************************************
238// simple space - reports all n^2 object intersections
239
240struct dxSimpleSpace : public dxSpace {
241 dxSimpleSpace (dSpaceID _space);
242 void cleanGeoms();
243 void collide (void *data, dNearCallback *callback);
244 void collide2 (void *data, dxGeom *geom, dNearCallback *callback);
245};
246
247
248dxSimpleSpace::dxSimpleSpace (dSpaceID _space) : dxSpace (_space)
249{
250 type = dSimpleSpaceClass;
251}
252
253
254void dxSimpleSpace::cleanGeoms()
255{
256 // compute the AABBs of all dirty geoms, and clear the dirty flags
257 lock_count++;
258 for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) {
259 if (IS_SPACE(g)) {
260 ((dxSpace*)g)->cleanGeoms();
261 }
262 g->recomputeAABB();
263 g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
264 }
265 lock_count--;
266}
267
268
269void dxSimpleSpace::collide (void *data, dNearCallback *callback)
270{
271 dAASSERT (callback);
272
273 lock_count++;
274 cleanGeoms();
275
276 // intersect all bounding boxes
277 for (dxGeom *g1=first; g1; g1=g1->next) {
278 if (GEOM_ENABLED(g1)){
279 for (dxGeom *g2=g1->next; g2; g2=g2->next) {
280 if (GEOM_ENABLED(g2)){
281 collideAABBs (g1,g2,data,callback);
282 }
283 }
284 }
285 }
286
287 lock_count--;
288}
289
290
291void dxSimpleSpace::collide2 (void *data, dxGeom *geom,
292 dNearCallback *callback)
293{
294 dAASSERT (geom && callback);
295
296 lock_count++;
297 cleanGeoms();
298 geom->recomputeAABB();
299
300 // intersect bounding boxes
301 for (dxGeom *g=first; g; g=g->next) {
302 if (GEOM_ENABLED(g)){
303 collideAABBs (g,geom,data,callback);
304 }
305 }
306
307 lock_count--;
308}
309
310//****************************************************************************
311// utility stuff for hash table space
312
313// kind of silly, but oh well...
314#ifndef MAXINT
315#define MAXINT ((int)((((unsigned int)(-1)) << 1) >> 1))
316#endif
317
318
319// prime[i] is the largest prime smaller than 2^i
320#define NUM_PRIMES 31
321static long int prime[NUM_PRIMES] = {1L,2L,3L,7L,13L,31L,61L,127L,251L,509L,
322 1021L,2039L,4093L,8191L,16381L,32749L,65521L,131071L,262139L,
323 524287L,1048573L,2097143L,4194301L,8388593L,16777213L,33554393L,
324 67108859L,134217689L,268435399L,536870909L,1073741789L};
325
326
327// an axis aligned bounding box in the hash table
328struct dxAABB {
329 dxAABB *next; // next in the list of all AABBs
330 int level; // the level this is stored in (cell size = 2^level)
331 int dbounds[6]; // AABB bounds, discretized to cell size
332 dxGeom *geom; // corresponding geometry object (AABB stored here)
333 int index; // index of this AABB, starting from 0
334};
335
336
337// a hash table node that represents an AABB that intersects a particular cell
338// at a particular level
339struct Node {
340 Node *next; // next node in hash table collision list, 0 if none
341 int x,y,z; // cell position in space, discretized to cell size
342 dxAABB *aabb; // axis aligned bounding box that intersects this cell
343};
344
345
346// return the `level' of an AABB. the AABB will be put into cells at this
347// level - the cell size will be 2^level. the level is chosen to be the
348// smallest value such that the AABB occupies no more than 8 cells, regardless
349// of its placement. this means that:
350// size/2 < q <= size
351// where q is the maximum AABB dimension.
352
353static int findLevel (dReal bounds[6])
354{
355 if (bounds[0] <= -dInfinity || bounds[1] >= dInfinity ||
356 bounds[2] <= -dInfinity || bounds[3] >= dInfinity ||
357 bounds[4] <= -dInfinity || bounds[5] >= dInfinity) {
358 return MAXINT;
359 }
360
361 // compute q
362 dReal q,q2;
363 q = bounds[1] - bounds[0]; // x bounds
364 q2 = bounds[3] - bounds[2]; // y bounds
365 if (q2 > q) q = q2;
366 q2 = bounds[5] - bounds[4]; // z bounds
367 if (q2 > q) q = q2;
368
369 // find level such that 0.5 * 2^level < q <= 2^level
370 int level;
371 frexp (q,&level); // q = (0.5 .. 1.0) * 2^level (definition of frexp)
372 return level;
373}
374
375
376// find a virtual memory address for a cell at the given level and x,y,z
377// position.
378// @@@ currently this is not very sophisticated, e.g. the scaling
379// factors could be better designed to avoid collisions, and they should
380// probably depend on the hash table physical size.
381
382static unsigned long getVirtualAddress (int level, int x, int y, int z)
383{
384 return level*1000 + x*100 + y*10 + z;
385}
386
387//****************************************************************************
388// hash space
389
390struct dxHashSpace : public dxSpace {
391 int global_minlevel; // smallest hash table level to put AABBs in
392 int global_maxlevel; // objects that need a level larger than this will be
393 // put in a "big objects" list instead of a hash table
394
395 dxHashSpace (dSpaceID _space);
396 void setLevels (int minlevel, int maxlevel);
397 void getLevels (int *minlevel, int *maxlevel);
398 void cleanGeoms();
399 void collide (void *data, dNearCallback *callback);
400 void collide2 (void *data, dxGeom *geom, dNearCallback *callback);
401};
402
403
404dxHashSpace::dxHashSpace (dSpaceID _space) : dxSpace (_space)
405{
406 type = dHashSpaceClass;
407 global_minlevel = -3;
408 global_maxlevel = 10;
409}
410
411
412void dxHashSpace::setLevels (int minlevel, int maxlevel)
413{
414 dAASSERT (minlevel <= maxlevel);
415 global_minlevel = minlevel;
416 global_maxlevel = maxlevel;
417}
418
419
420void dxHashSpace::getLevels (int *minlevel, int *maxlevel)
421{
422 if (minlevel) *minlevel = global_minlevel;
423 if (maxlevel) *maxlevel = global_maxlevel;
424}
425
426
427void dxHashSpace::cleanGeoms()
428{
429 // compute the AABBs of all dirty geoms, and clear the dirty flags
430 lock_count++;
431 for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) {
432 if (IS_SPACE(g)) {
433 ((dxSpace*)g)->cleanGeoms();
434 }
435 g->recomputeAABB();
436 g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
437 }
438 lock_count--;
439}
440
441
442void dxHashSpace::collide (void *data, dNearCallback *callback)
443{
444 dAASSERT(this && callback);
445 dxGeom *geom;
446 dxAABB *aabb;
447 int i,maxlevel;
448
449 // 0 or 1 geoms can't collide with anything
450 if (count < 2) return;
451
452 lock_count++;
453 cleanGeoms();
454
455 // create a list of auxiliary information for all geom axis aligned bounding
456 // boxes. set the level for all AABBs. put AABBs larger than the space's
457 // global_maxlevel in the big_boxes list, check everything else against
458 // that list at the end. for AABBs that are not too big, record the maximum
459 // level that we need.
460
461 int n = 0; // number of AABBs in main list
462 dxAABB *first_aabb = 0; // list of AABBs in hash table
463 dxAABB *big_boxes = 0; // list of AABBs too big for hash table
464 maxlevel = global_minlevel - 1;
465 for (geom = first; geom; geom=geom->next) {
466 if (!GEOM_ENABLED(geom)){
467 continue;
468 }
469 dxAABB *aabb = (dxAABB*) ALLOCA (sizeof(dxAABB));
470 aabb->geom = geom;
471 // compute level, but prevent cells from getting too small
472 int level = findLevel (geom->aabb);
473 if (level < global_minlevel) level = global_minlevel;
474 if (level <= global_maxlevel) {
475 // aabb goes in main list
476 aabb->next = first_aabb;
477 first_aabb = aabb;
478 aabb->level = level;
479 if (level > maxlevel) maxlevel = level;
480 // cellsize = 2^level
481 dReal cellsize = (dReal) ldexp (1.0,level);
482 // discretize AABB position to cell size
483 for (i=0; i < 6; i++) aabb->dbounds[i] = (int)
484 floor (geom->aabb[i]/cellsize);
485 // set AABB index
486 aabb->index = n;
487 n++;
488 }
489 else {
490 // aabb is too big, put it in the big_boxes list. we don't care about
491 // setting level, dbounds, index, or the maxlevel
492 aabb->next = big_boxes;
493 big_boxes = aabb;
494 }
495 }
496
497 // for `n' objects, an n*n array of bits is used to record if those objects
498 // have been intersection-tested against each other yet. this array can
499 // grow large with high n, but oh well...
500 int tested_rowsize = (n+7) >> 3; // number of bytes needed for n bits
501 unsigned char *tested = (unsigned char *) ALLOCA (n * tested_rowsize);
502 memset (tested,0,n * tested_rowsize);
503
504 // create a hash table to store all AABBs. each AABB may take up to 8 cells.
505 // we use chaining to resolve collisions, but we use a relatively large table
506 // to reduce the chance of collisions.
507
508 // compute hash table size sz to be a prime > 8*n
509 for (i=0; i<NUM_PRIMES; i++) {
510 if (prime[i] >= (8*n)) break;
511 }
512 if (i >= NUM_PRIMES) i = NUM_PRIMES-1; // probably pointless
513 int sz = prime[i];
514
515 // allocate and initialize hash table node pointers
516 Node **table = (Node **) ALLOCA (sizeof(Node*) * sz);
517 for (i=0; i<sz; i++) table[i] = 0;
518
519 // add each AABB to the hash table (may need to add it to up to 8 cells)
520 for (aabb=first_aabb; aabb; aabb=aabb->next) {
521 int *dbounds = aabb->dbounds;
522 for (int xi = dbounds[0]; xi <= dbounds[1]; xi++) {
523 for (int yi = dbounds[2]; yi <= dbounds[3]; yi++) {
524 for (int zi = dbounds[4]; zi <= dbounds[5]; zi++) {
525 // get the hash index
526 unsigned long hi = getVirtualAddress (aabb->level,xi,yi,zi) % sz;
527 // add a new node to the hash table
528 Node *node = (Node*) ALLOCA (sizeof (Node));
529 node->x = xi;
530 node->y = yi;
531 node->z = zi;
532 node->aabb = aabb;
533 node->next = table[hi];
534 table[hi] = node;
535 }
536 }
537 }
538 }
539
540 // now that all AABBs are loaded into the hash table, we do the actual
541 // collision detection. for all AABBs, check for other AABBs in the
542 // same cells for collisions, and then check for other AABBs in all
543 // intersecting higher level cells.
544
545 int db[6]; // discrete bounds at current level
546 for (aabb=first_aabb; aabb; aabb=aabb->next) {
547 // we are searching for collisions with aabb
548 for (i=0; i<6; i++) db[i] = aabb->dbounds[i];
549 for (int level = aabb->level; level <= maxlevel; level++) {
550 for (int xi = db[0]; xi <= db[1]; xi++) {
551 for (int yi = db[2]; yi <= db[3]; yi++) {
552 for (int zi = db[4]; zi <= db[5]; zi++) {
553 // get the hash index
554 unsigned long hi = getVirtualAddress (level,xi,yi,zi) % sz;
555 // search all nodes at this index
556 Node *node;
557 for (node = table[hi]; node; node=node->next) {
558 // node points to an AABB that may intersect aabb
559 if (node->aabb == aabb) continue;
560 if (node->aabb->level == level &&
561 node->x == xi && node->y == yi && node->z == zi) {
562 // see if aabb and node->aabb have already been tested
563 // against each other
564 unsigned char mask;
565 if (aabb->index <= node->aabb->index) {
566 i = (aabb->index * tested_rowsize)+(node->aabb->index >> 3);
567 mask = 1 << (node->aabb->index & 7);
568 }
569 else {
570 i = (node->aabb->index * tested_rowsize)+(aabb->index >> 3);
571 mask = 1 << (aabb->index & 7);
572 }
573 dIASSERT (i >= 0 && i < (tested_rowsize*n));
574 if ((tested[i] & mask)==0) {
575 collideAABBs (aabb->geom,node->aabb->geom,data,callback);
576 }
577 tested[i] |= mask;
578 }
579 }
580 }
581 }
582 }
583 // get the discrete bounds for the next level up
584 for (i=0; i<6; i++) db[i] >>= 1;
585 }
586 }
587
588 // every AABB in the normal list must now be intersected against every
589 // AABB in the big_boxes list. so let's hope there are not too many objects
590 // in the big_boxes list.
591 for (aabb=first_aabb; aabb; aabb=aabb->next) {
592 for (dxAABB *aabb2=big_boxes; aabb2; aabb2=aabb2->next) {
593 collideAABBs (aabb->geom,aabb2->geom,data,callback);
594 }
595 }
596
597 // intersected all AABBs in the big_boxes list together
598 for (aabb=big_boxes; aabb; aabb=aabb->next) {
599 for (dxAABB *aabb2=aabb->next; aabb2; aabb2=aabb2->next) {
600 collideAABBs (aabb->geom,aabb2->geom,data,callback);
601 }
602 }
603
604 lock_count--;
605}
606
607
608void dxHashSpace::collide2 (void *data, dxGeom *geom,
609 dNearCallback *callback)
610{
611 dAASSERT (geom && callback);
612
613 // this could take advantage of the hash structure to avoid
614 // O(n2) complexity, but it does not yet.
615
616 lock_count++;
617 cleanGeoms();
618 geom->recomputeAABB();
619
620 // intersect bounding boxes
621 for (dxGeom *g=first; g; g=g->next) {
622 if (GEOM_ENABLED(g)) collideAABBs (g,geom,data,callback);
623 }
624
625 lock_count--;
626}
627
628//****************************************************************************
629// space functions
630
631dxSpace *dSimpleSpaceCreate (dxSpace *space)
632{
633 return new dxSimpleSpace (space);
634}
635
636
637dxSpace *dHashSpaceCreate (dxSpace *space)
638{
639 return new dxHashSpace (space);
640}
641
642
643void dHashSpaceSetLevels (dxSpace *space, int minlevel, int maxlevel)
644{
645 dAASSERT (space);
646 dUASSERT (minlevel <= maxlevel,"must have minlevel <= maxlevel");
647 dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space");
648 dxHashSpace *hspace = (dxHashSpace*) space;
649 hspace->setLevels (minlevel,maxlevel);
650}
651
652
653void dHashSpaceGetLevels (dxSpace *space, int *minlevel, int *maxlevel)
654{
655 dAASSERT (space);
656 dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space");
657 dxHashSpace *hspace = (dxHashSpace*) space;
658 hspace->getLevels (minlevel,maxlevel);
659}
660
661
662void dSpaceDestroy (dxSpace *space)
663{
664 dAASSERT (space);
665 dUASSERT (dGeomIsSpace(space),"argument not a space");
666 dGeomDestroy (space);
667}
668
669
670void dSpaceSetCleanup (dxSpace *space, int mode)
671{
672 dAASSERT (space);
673 dUASSERT (dGeomIsSpace(space),"argument not a space");
674 space->setCleanup (mode);
675}
676
677
678int dSpaceGetCleanup (dxSpace *space)
679{
680 dAASSERT (space);
681 dUASSERT (dGeomIsSpace(space),"argument not a space");
682 return space->getCleanup();
683}
684
685
686void dSpaceAdd (dxSpace *space, dxGeom *g)
687{
688 dAASSERT (space);
689 dUASSERT (dGeomIsSpace(space),"argument not a space");
690 CHECK_NOT_LOCKED (space);
691 space->add (g);
692}
693
694
695void dSpaceRemove (dxSpace *space, dxGeom *g)
696{
697 dAASSERT (space);
698 dUASSERT (dGeomIsSpace(space),"argument not a space");
699 CHECK_NOT_LOCKED (space);
700 space->remove (g);
701}
702
703
704int dSpaceQuery (dxSpace *space, dxGeom *g)
705{
706 dAASSERT (space);
707 dUASSERT (dGeomIsSpace(space),"argument not a space");
708 return space->query (g);
709}
710
711void dSpaceClean (dxSpace *space){
712 dAASSERT (space);
713 dUASSERT (dGeomIsSpace(space),"argument not a space");
714
715 space->cleanGeoms();
716}
717
718int dSpaceGetNumGeoms (dxSpace *space)
719{
720 dAASSERT (space);
721 dUASSERT (dGeomIsSpace(space),"argument not a space");
722 return space->getNumGeoms();
723}
724
725
726dGeomID dSpaceGetGeom (dxSpace *space, int i)
727{
728 dAASSERT (space);
729 dUASSERT (dGeomIsSpace(space),"argument not a space");
730 return space->getGeom (i);
731}
732
733
734void dSpaceCollide (dxSpace *space, void *data, dNearCallback *callback)
735{
736 dAASSERT (space && callback);
737 dUASSERT (dGeomIsSpace(space),"argument not a space");
738 space->collide (data,callback);
739}
740
741
742void dSpaceCollide2 (dxGeom *g1, dxGeom *g2, void *data,
743 dNearCallback *callback)
744{
745 dAASSERT (g1 && g2 && callback);
746 dxSpace *s1,*s2;
747
748 // see if either geom is a space
749 if (IS_SPACE(g1)) s1 = (dxSpace*) g1; else s1 = 0;
750 if (IS_SPACE(g2)) s2 = (dxSpace*) g2; else s2 = 0;
751
752 // handle the four space/geom cases
753 if (s1) {
754 if (s2) {
755 // g1 and g2 are spaces.
756 if (s1==s2) {
757 // collide a space with itself --> interior collision
758 s1->collide (data,callback);
759 }
760 else {
761 // iterate through the space that has the fewest geoms, calling
762 // collide2 in the other space for each one.
763 if (s1->count < s2->count) {
764 for (dxGeom *g = s1->first; g; g=g->next) {
765 s2->collide2 (data,g,callback);
766 }
767 }
768 else {
769 for (dxGeom *g = s2->first; g; g=g->next) {
770 s1->collide2 (data,g,callback);
771 }
772 }
773 }
774 }
775 else {
776 // g1 is a space, g2 is a geom
777 s1->collide2 (data,g2,callback);
778 }
779 }
780 else {
781 if (s2) {
782 // g1 is a geom, g2 is a space
783 s2->collide2 (data,g1,callback);
784 }
785 else {
786 // g1 and g2 are geoms, call the callback directly
787 callback (data,g1,g2);
788 }
789 }
790}
diff --git a/libraries/ode-0.9/ode/src/collision_space_internal.h b/libraries/ode-0.9/ode/src/collision_space_internal.h
deleted file mode 100644
index 004276a..0000000
--- a/libraries/ode-0.9/ode/src/collision_space_internal.h
+++ /dev/null
@@ -1,84 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25stuff common to all spaces
26
27*/
28
29#ifndef _ODE_COLLISION_SPACE_INTERNAL_H_
30#define _ODE_COLLISION_SPACE_INTERNAL_H_
31
32#define ALLOCA(x) dALLOCA16(x)
33
34#define CHECK_NOT_LOCKED(space) \
35 dUASSERT ((space)==0 || (space)->lock_count==0, \
36 "invalid operation for locked space");
37
38
39// collide two geoms together. for the hash table space, this is
40// called if the two AABBs inhabit the same hash table cells.
41// this only calls the callback function if the AABBs actually
42// intersect. if a geom has an AABB test function, that is called to
43// provide a further refinement of the intersection.
44//
45// NOTE: this assumes that the geom AABBs are valid on entry
46// and that both geoms are enabled.
47
48static void collideAABBs (dxGeom *g1, dxGeom *g2,
49 void *data, dNearCallback *callback)
50{
51 dIASSERT((g1->gflags & GEOM_AABB_BAD)==0);
52 dIASSERT((g2->gflags & GEOM_AABB_BAD)==0);
53
54 // no contacts if both geoms on the same body, and the body is not 0
55 if (g1->body == g2->body && g1->body) return;
56
57 // test if the category and collide bitfields match
58 if ( ((g1->category_bits & g2->collide_bits) ||
59 (g2->category_bits & g1->collide_bits)) == 0) {
60 return;
61 }
62
63 // if the bounding boxes are disjoint then don't do anything
64 dReal *bounds1 = g1->aabb;
65 dReal *bounds2 = g2->aabb;
66 if (bounds1[0] > bounds2[1] ||
67 bounds1[1] < bounds2[0] ||
68 bounds1[2] > bounds2[3] ||
69 bounds1[3] < bounds2[2] ||
70 bounds1[4] > bounds2[5] ||
71 bounds1[5] < bounds2[4]) {
72 return;
73 }
74
75 // check if either object is able to prove that it doesn't intersect the
76 // AABB of the other
77 if (g1->AABBTest (g2,bounds2) == 0) return;
78 if (g2->AABBTest (g1,bounds1) == 0) return;
79
80 // the objects might actually intersect - call the space callback function
81 callback (data,g1,g2);
82}
83
84#endif
diff --git a/libraries/ode-0.9/ode/src/collision_std.h b/libraries/ode-0.9/ode/src/collision_std.h
deleted file mode 100644
index d203ad0..0000000
--- a/libraries/ode-0.9/ode/src/collision_std.h
+++ /dev/null
@@ -1,172 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25the standard ODE geometry primitives.
26
27*/
28
29#ifndef _ODE_COLLISION_STD_H_
30#define _ODE_COLLISION_STD_H_
31
32#include <set>
33#include <ode/common.h>
34#include "collision_kernel.h"
35
36
37// primitive collision functions - these have the dColliderFn interface, i.e.
38// the same interface as dCollide(). the first and second geom arguments must
39// have the specified types.
40
41int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags,
42 dContactGeom *contact, int skip);
43int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags,
44 dContactGeom *contact, int skip);
45int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags,
46 dContactGeom *contact, int skip);
47int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags,
48 dContactGeom *contact, int skip);
49int dCollideBoxPlane (dxGeom *o1, dxGeom *o2,
50 int flags, dContactGeom *contact, int skip);
51int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags,
52 dContactGeom *contact, int skip);
53int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags,
54 dContactGeom *contact, int skip);
55int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2,
56 int flags, dContactGeom *contact, int skip);
57int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags,
58 dContactGeom *contact, int skip);
59int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags,
60 dContactGeom *contact, int skip);
61int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags,
62 dContactGeom *contact, int skip);
63int dCollideRayCapsule (dxGeom *o1, dxGeom *o2,
64 int flags, dContactGeom *contact, int skip);
65int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags,
66 dContactGeom *contact, int skip);
67int dCollideRayCylinder (dxGeom *o1, dxGeom *o2, int flags,
68 dContactGeom *contact, int skip);
69
70// Cylinder - Box/Sphere by (C) CroTeam
71// Ported by Nguyen Binh
72int dCollideCylinderBox(dxGeom *o1, dxGeom *o2,
73 int flags, dContactGeom *contact, int skip);
74int dCollideCylinderSphere(dxGeom *gCylinder, dxGeom *gSphere,
75 int flags, dContactGeom *contact, int skip);
76int dCollideCylinderPlane(dxGeom *gCylinder, dxGeom *gPlane,
77 int flags, dContactGeom *contact, int skip);
78
79//--> Convex Collision
80int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags,
81 dContactGeom *contact, int skip);
82int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags,
83 dContactGeom *contact, int skip);
84int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags,
85 dContactGeom *contact, int skip);
86int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2,
87 int flags, dContactGeom *contact, int skip);
88int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
89 dContactGeom *contact, int skip);
90int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags,
91 dContactGeom *contact, int skip);
92//<-- Convex Collision
93
94// dHeightfield
95int dCollideHeightfield( dxGeom *o1, dxGeom *o2,
96 int flags, dContactGeom *contact, int skip );
97
98//****************************************************************************
99// the basic geometry objects
100
101struct dxSphere : public dxGeom {
102 dReal radius; // sphere radius
103 dxSphere (dSpaceID space, dReal _radius);
104 void computeAABB();
105};
106
107
108struct dxBox : public dxGeom {
109 dVector3 side; // side lengths (x,y,z)
110 dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz);
111 void computeAABB();
112};
113
114
115struct dxCapsule : public dxGeom {
116 dReal radius,lz; // radius, length along z axis
117 dxCapsule (dSpaceID space, dReal _radius, dReal _length);
118 void computeAABB();
119};
120
121
122struct dxCylinder : public dxGeom {
123 dReal radius,lz; // radius, length along z axis
124 dxCylinder (dSpaceID space, dReal _radius, dReal _length);
125 void computeAABB();
126};
127
128
129struct dxPlane : public dxGeom {
130 dReal p[4];
131 dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d);
132 void computeAABB();
133};
134
135
136struct dxRay : public dxGeom {
137 dReal length;
138 dxRay (dSpaceID space, dReal _length);
139 void computeAABB();
140};
141
142typedef 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 */
143struct dxConvex : public dxGeom
144{
145
146 dReal *planes; /*!< An array of planes in the form:
147 normal X, normal Y, normal Z,Distance
148 */
149 dReal *points; /*!< An array of points X,Y,Z */
150 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*/
151 unsigned int planecount; /*!< Amount of planes in planes */
152 unsigned int pointcount;/*!< Amount of points in points */
153 dReal saabb[6];/*!< Static AABB */
154 std::set<edge> edges;
155 dxConvex(dSpaceID space,
156 dReal *planes,
157 unsigned int planecount,
158 dReal *points,
159 unsigned int pointcount,
160 unsigned int *polygons);
161 ~dxConvex()
162 {
163 //fprintf(stdout,"dxConvex Destroy\n");
164 }
165 void computeAABB();
166 private:
167 // For Internal Use Only
168 void FillEdges();
169};
170
171
172#endif
diff --git a/libraries/ode-0.9/ode/src/collision_transform.cpp b/libraries/ode-0.9/ode/src/collision_transform.cpp
deleted file mode 100644
index 85fd623..0000000
--- a/libraries/ode-0.9/ode/src/collision_transform.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25geom transform
26
27*/
28
29#include <ode/collision.h>
30#include <ode/matrix.h>
31#include <ode/rotation.h>
32#include <ode/odemath.h>
33#include "collision_transform.h"
34#include "collision_util.h"
35
36#ifdef _MSC_VER
37#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
38#endif
39
40//****************************************************************************
41// dxGeomTransform class
42
43struct dxGeomTransform : public dxGeom {
44 dxGeom *obj; // object that is being transformed
45 int cleanup; // 1 to destroy obj when destroyed
46 int infomode; // 1 to put Tx geom in dContactGeom g1
47
48 // cached final object transform (body tx + relative tx). this is set by
49 // computeAABB(), and it is valid while the AABB is valid.
50 dxPosR transform_posr;
51
52 dxGeomTransform (dSpaceID space);
53 ~dxGeomTransform();
54 void computeAABB();
55 void computeFinalTx();
56};
57/*
58void RunMe()
59{
60 printf("sizeof body = %i\n", sizeof(dxBody));
61 printf("sizeof geom = %i\n", sizeof(dxGeom));
62 printf("sizeof geomtransform = %i\n", sizeof(dxGeomTransform));
63 printf("sizeof posr = %i\n", sizeof(dxPosR));
64}
65*/
66
67dxGeomTransform::dxGeomTransform (dSpaceID space) : dxGeom (space,1)
68{
69 type = dGeomTransformClass;
70 obj = 0;
71 cleanup = 0;
72 infomode = 0;
73 dSetZero (transform_posr.pos,4);
74 dRSetIdentity (transform_posr.R);
75}
76
77
78dxGeomTransform::~dxGeomTransform()
79{
80 if (obj && cleanup) delete obj;
81}
82
83
84void dxGeomTransform::computeAABB()
85{
86 if (!obj) {
87 dSetZero (aabb,6);
88 return;
89 }
90
91 // backup the relative pos and R pointers of the encapsulated geom object
92 dxPosR* posr_bak = obj->final_posr;
93
94 // compute temporary pos and R for the encapsulated geom object
95 computeFinalTx();
96 obj->final_posr = &transform_posr;
97
98 // compute the AABB
99 obj->computeAABB();
100 memcpy (aabb,obj->aabb,6*sizeof(dReal));
101
102 // restore the pos and R
103 obj->final_posr = posr_bak;
104}
105
106
107// utility function for dCollideTransform() : compute final pos and R
108// for the encapsulated geom object
109
110void dxGeomTransform::computeFinalTx()
111{
112 dMULTIPLY0_331 (transform_posr.pos,final_posr->R,obj->final_posr->pos);
113 transform_posr.pos[0] += final_posr->pos[0];
114 transform_posr.pos[1] += final_posr->pos[1];
115 transform_posr.pos[2] += final_posr->pos[2];
116 dMULTIPLY0_333 (transform_posr.R,final_posr->R,obj->final_posr->R);
117}
118
119//****************************************************************************
120// collider function:
121// this collides a transformed geom with another geom. the other geom can
122// also be a transformed geom, but this case is not handled specially.
123
124int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags,
125 dContactGeom *contact, int skip)
126{
127 dIASSERT (skip >= (int)sizeof(dContactGeom));
128 dIASSERT (o1->type == dGeomTransformClass);
129
130 dxGeomTransform *tr = (dxGeomTransform*) o1;
131 if (!tr->obj) return 0;
132 dUASSERT (tr->obj->parent_space==0,
133 "GeomTransform encapsulated object must not be in a space");
134 dUASSERT (tr->obj->body==0,
135 "GeomTransform encapsulated object must not be attached "
136 "to a body");
137
138 // backup the relative pos and R pointers of the encapsulated geom object,
139 // and the body pointer
140 dxPosR *posr_bak = tr->obj->final_posr;
141 dxBody *bodybak = tr->obj->body;
142
143 // compute temporary pos and R for the encapsulated geom object.
144 // note that final_pos and final_R are valid if no GEOM_AABB_BAD flag,
145 // because computeFinalTx() will have already been called in
146 // dxGeomTransform::computeAABB()
147
148 if (tr->gflags & GEOM_AABB_BAD) tr->computeFinalTx();
149 tr->obj->final_posr = &tr->transform_posr;
150 tr->obj->body = o1->body;
151
152 // do the collision
153 int n = dCollide (tr->obj,o2,flags,contact,skip);
154
155 // if required, adjust the 'g1' values in the generated contacts so that
156 // thay indicated the GeomTransform object instead of the encapsulated
157 // object.
158 if (tr->infomode) {
159 for (int i=0; i<n; i++) {
160 dContactGeom *c = CONTACT(contact,skip*i);
161 c->g1 = o1;
162 }
163 }
164
165 // restore the pos, R and body
166 tr->obj->final_posr = posr_bak;
167 tr->obj->body = bodybak;
168 return n;
169}
170
171//****************************************************************************
172// public API
173
174dGeomID dCreateGeomTransform (dSpaceID space)
175{
176 return new dxGeomTransform (space);
177}
178
179
180void dGeomTransformSetGeom (dGeomID g, dGeomID obj)
181{
182 dUASSERT (g && g->type == dGeomTransformClass,
183 "argument not a geom transform");
184 dxGeomTransform *tr = (dxGeomTransform*) g;
185 if (tr->obj && tr->cleanup) delete tr->obj;
186 tr->obj = obj;
187}
188
189
190dGeomID dGeomTransformGetGeom (dGeomID g)
191{
192 dUASSERT (g && g->type == dGeomTransformClass,
193 "argument not a geom transform");
194 dxGeomTransform *tr = (dxGeomTransform*) g;
195 return tr->obj;
196}
197
198
199void dGeomTransformSetCleanup (dGeomID g, int mode)
200{
201 dUASSERT (g && g->type == dGeomTransformClass,
202 "argument not a geom transform");
203 dxGeomTransform *tr = (dxGeomTransform*) g;
204 tr->cleanup = mode;
205}
206
207
208int dGeomTransformGetCleanup (dGeomID g)
209{
210 dUASSERT (g && g->type == dGeomTransformClass,
211 "argument not a geom transform");
212 dxGeomTransform *tr = (dxGeomTransform*) g;
213 return tr->cleanup;
214}
215
216
217void dGeomTransformSetInfo (dGeomID g, int mode)
218{
219 dUASSERT (g && g->type == dGeomTransformClass,
220 "argument not a geom transform");
221 dxGeomTransform *tr = (dxGeomTransform*) g;
222 tr->infomode = mode;
223}
224
225
226int dGeomTransformGetInfo (dGeomID g)
227{
228 dUASSERT (g && g->type == dGeomTransformClass,
229 "argument not a geom transform");
230 dxGeomTransform *tr = (dxGeomTransform*) g;
231 return tr->infomode;
232}
diff --git a/libraries/ode-0.9/ode/src/collision_transform.h b/libraries/ode-0.9/ode/src/collision_transform.h
deleted file mode 100644
index 406a687..0000000
--- a/libraries/ode-0.9/ode/src/collision_transform.h
+++ /dev/null
@@ -1,40 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25geom transform
26
27*/
28
29#ifndef _ODE_COLLISION_TRANSFORM_H_
30#define _ODE_COLLISION_TRANSFORM_H_
31
32#include <ode/common.h>
33#include "collision_kernel.h"
34
35
36int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags,
37 dContactGeom *contact, int skip);
38
39
40#endif
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_box.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_box.cpp
deleted file mode 100644
index 0194d02..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_box.cpp
+++ /dev/null
@@ -1,1497 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23
24/*************************************************************************
25 * *
26 * Triangle-box collider by Alen Ladavac and Vedran Klanac. *
27 * Ported to ODE by Oskari Nyman. *
28 * *
29 *************************************************************************/
30
31
32#include <ode/collision.h>
33#include <ode/matrix.h>
34#include <ode/rotation.h>
35#include <ode/odemath.h>
36#include "collision_util.h"
37
38#define TRIMESH_INTERNAL
39#include "collision_trimesh_internal.h"
40
41#if dTRIMESH_ENABLED
42
43
44static void
45GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,
46 dxGeom* in_g1, dxGeom* in_g2,
47 const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
48 int& OutTriCount);
49
50
51// largest number, double or float
52#if defined(dSINGLE)
53 #define MAXVALUE FLT_MAX
54#else
55 #define MAXVALUE DBL_MAX
56#endif
57
58
59// dVector3
60// r=a-b
61#define SUBTRACT(a,b,r) do{ \
62 (r)[0]=(a)[0] - (b)[0]; \
63 (r)[1]=(a)[1] - (b)[1]; \
64 (r)[2]=(a)[2] - (b)[2]; }while(0)
65
66
67// dVector3
68// a=b
69#define SET(a,b) do{ \
70 (a)[0]=(b)[0]; \
71 (a)[1]=(b)[1]; \
72 (a)[2]=(b)[2]; }while(0)
73
74
75// dMatrix3
76// a=b
77#define SETM(a,b) do{ \
78 (a)[0]=(b)[0]; \
79 (a)[1]=(b)[1]; \
80 (a)[2]=(b)[2]; \
81 (a)[3]=(b)[3]; \
82 (a)[4]=(b)[4]; \
83 (a)[5]=(b)[5]; \
84 (a)[6]=(b)[6]; \
85 (a)[7]=(b)[7]; \
86 (a)[8]=(b)[8]; \
87 (a)[9]=(b)[9]; \
88 (a)[10]=(b)[10]; \
89 (a)[11]=(b)[11]; }while(0)
90
91
92// dVector3
93// r=a+b
94#define ADD(a,b,r) do{ \
95 (r)[0]=(a)[0] + (b)[0]; \
96 (r)[1]=(a)[1] + (b)[1]; \
97 (r)[2]=(a)[2] + (b)[2]; }while(0)
98
99
100// dMatrix3, int, dVector3
101// v=column a from m
102#define GETCOL(m,a,v) do{ \
103 (v)[0]=(m)[(a)+0]; \
104 (v)[1]=(m)[(a)+4]; \
105 (v)[2]=(m)[(a)+8]; }while(0)
106
107
108// dVector4, dVector3
109// distance between plane p and point v
110#define POINTDISTANCE(p,v) \
111 ( p[0]*v[0] + p[1]*v[1] + p[2]*v[2] + p[3] )
112
113
114// dVector4, dVector3, dReal
115// construct plane from normal and d
116#define CONSTRUCTPLANE(plane,normal,d) do{ \
117 plane[0]=normal[0];\
118 plane[1]=normal[1];\
119 plane[2]=normal[2];\
120 plane[3]=d; }while(0)
121
122
123// dVector3
124// length of vector a
125#define LENGTHOF(a) \
126 dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])
127
128
129// box data
130static dMatrix3 mHullBoxRot;
131static dVector3 vHullBoxPos;
132static dVector3 vBoxHalfSize;
133
134// mesh data
135static dVector3 vHullDstPos;
136
137// global collider data
138static dVector3 vBestNormal;
139static dReal fBestDepth;
140static int iBestAxis = 0;
141static int iExitAxis = 0;
142static dVector3 vE0, vE1, vE2, vN;
143
144// global info for contact creation
145static int iFlags;
146static dContactGeom *ContactGeoms;
147static int iStride;
148static dxGeom *Geom1;
149static dxGeom *Geom2;
150static int ctContacts = 0;
151
152
153
154// Test normal of mesh face as separating axis for intersection
155static bool _cldTestNormal( dReal fp0, dReal fR, dVector3 vNormal, int iAxis )
156{
157 // calculate overlapping interval of box and triangle
158 dReal fDepth = fR+fp0;
159
160 // if we do not overlap
161 if ( fDepth<0 ) {
162 // do nothing
163 return false;
164 }
165
166 // calculate normal's length
167 dReal fLength = LENGTHOF(vNormal);
168 // if long enough
169 if ( fLength > 0.0f ) {
170
171 dReal fOneOverLength = 1.0f/fLength;
172 // normalize depth
173 fDepth = fDepth*fOneOverLength;
174
175 // get minimum depth
176 if (fDepth<fBestDepth) {
177 vBestNormal[0] = -vNormal[0]*fOneOverLength;
178 vBestNormal[1] = -vNormal[1]*fOneOverLength;
179 vBestNormal[2] = -vNormal[2]*fOneOverLength;
180 iBestAxis = iAxis;
181 //dAASSERT(fDepth>=0);
182 fBestDepth = fDepth;
183 }
184
185 }
186
187 return true;
188}
189
190
191
192
193// Test box axis as separating axis
194static bool _cldTestFace( dReal fp0, dReal fp1, dReal fp2, dReal fR, dReal fD,
195 dVector3 vNormal, int iAxis )
196{
197 dReal fMin, fMax;
198
199 // find min of triangle interval
200 if ( fp0 < fp1 ) {
201 if ( fp0 < fp2 ) {
202 fMin = fp0;
203 } else {
204 fMin = fp2;
205 }
206 } else {
207 if( fp1 < fp2 ) {
208 fMin = fp1;
209 } else {
210 fMin = fp2;
211 }
212 }
213
214 // find max of triangle interval
215 if ( fp0 > fp1 ) {
216 if ( fp0 > fp2 ) {
217 fMax = fp0;
218 } else {
219 fMax = fp2;
220 }
221 } else {
222 if( fp1 > fp2 ) {
223 fMax = fp1;
224 } else {
225 fMax = fp2;
226 }
227 }
228
229 // calculate minimum and maximum depth
230 dReal fDepthMin = fR - fMin;
231 dReal fDepthMax = fMax + fR;
232
233 // if we dont't have overlapping interval
234 if ( fDepthMin < 0 || fDepthMax < 0 ) {
235 // do nothing
236 return false;
237 }
238
239 dReal fDepth = 0;
240
241 // if greater depth is on negative side
242 if ( fDepthMin > fDepthMax ) {
243 // use smaller depth (one from positive side)
244 fDepth = fDepthMax;
245 // flip normal direction
246 vNormal[0] = -vNormal[0];
247 vNormal[1] = -vNormal[1];
248 vNormal[2] = -vNormal[2];
249 fD = -fD;
250 // if greater depth is on positive side
251 } else {
252 // use smaller depth (one from negative side)
253 fDepth = fDepthMin;
254 }
255
256
257 // if lower depth than best found so far
258 if (fDepth<fBestDepth) {
259 // remember current axis as best axis
260 vBestNormal[0] = vNormal[0];
261 vBestNormal[1] = vNormal[1];
262 vBestNormal[2] = vNormal[2];
263 iBestAxis = iAxis;
264 //dAASSERT(fDepth>=0);
265 fBestDepth = fDepth;
266 }
267
268 return true;
269}
270
271
272
273
274
275// Test cross products of box axis and triangle edges as separating axis
276static bool _cldTestEdge( dReal fp0, dReal fp1, dReal fR, dReal fD,
277 dVector3 vNormal, int iAxis )
278{
279 dReal fMin, fMax;
280
281
282 // ===== Begin Patch by Francisco Leon, 2006/10/28 =====
283
284 // Fixed Null Normal. This prevents boxes passing
285 // through trimeshes at certain contact angles
286
287 fMin = vNormal[0] * vNormal[0] +
288 vNormal[1] * vNormal[1] +
289 vNormal[2] * vNormal[2];
290
291 if ( fMin <= dEpsilon ) /// THIS NORMAL WOULD BE DANGEROUS
292 return true;
293
294 // ===== Ending Patch by Francisco Leon =====
295
296
297 // calculate min and max interval values
298 if ( fp0 < fp1 ) {
299 fMin = fp0;
300 fMax = fp1;
301 } else {
302 fMin = fp1;
303 fMax = fp0;
304 }
305
306 // check if we overlapp
307 dReal fDepthMin = fR - fMin;
308 dReal fDepthMax = fMax + fR;
309
310 // if we don't overlapp
311 if ( fDepthMin < 0 || fDepthMax < 0 ) {
312 // do nothing
313 return false;
314 }
315
316 dReal fDepth;
317
318
319 // if greater depth is on negative side
320 if ( fDepthMin > fDepthMax ) {
321 // use smaller depth (one from positive side)
322 fDepth = fDepthMax;
323 // flip normal direction
324 vNormal[0] = -vNormal[0];
325 vNormal[1] = -vNormal[1];
326 vNormal[2] = -vNormal[2];
327 fD = -fD;
328 // if greater depth is on positive side
329 } else {
330 // use smaller depth (one from negative side)
331 fDepth = fDepthMin;
332 }
333
334 // calculate normal's length
335 dReal fLength = LENGTHOF(vNormal);
336
337 // if long enough
338 if ( fLength > 0.0f ) {
339
340 // normalize depth
341 dReal fOneOverLength = 1.0f/fLength;
342 fDepth = fDepth*fOneOverLength;
343 fD*=fOneOverLength;
344
345
346 // if lower depth than best found so far (favor face over edges)
347 if (fDepth*1.5f<fBestDepth) {
348 // remember current axis as best axis
349 vBestNormal[0] = vNormal[0]*fOneOverLength;
350 vBestNormal[1] = vNormal[1]*fOneOverLength;
351 vBestNormal[2] = vNormal[2]*fOneOverLength;
352 iBestAxis = iAxis;
353 //dAASSERT(fDepth>=0);
354 fBestDepth = fDepth;
355 }
356 }
357
358 return true;
359}
360
361
362
363
364
365// clip polygon with plane and generate new polygon points
366static void _cldClipPolyToPlane( dVector3 avArrayIn[], int ctIn,
367 dVector3 avArrayOut[], int &ctOut,
368 const dVector4 &plPlane )
369{
370 // start with no output points
371 ctOut = 0;
372
373 int i0 = ctIn-1;
374
375 // for each edge in input polygon
376 for (int i1=0; i1<ctIn; i0=i1, i1++) {
377
378
379 // calculate distance of edge points to plane
380 dReal fDistance0 = POINTDISTANCE( plPlane ,avArrayIn[i0] );
381 dReal fDistance1 = POINTDISTANCE( plPlane ,avArrayIn[i1] );
382
383
384 // if first point is in front of plane
385 if( fDistance0 >= 0 ) {
386 // emit point
387 avArrayOut[ctOut][0] = avArrayIn[i0][0];
388 avArrayOut[ctOut][1] = avArrayIn[i0][1];
389 avArrayOut[ctOut][2] = avArrayIn[i0][2];
390 ctOut++;
391 }
392
393 // if points are on different sides
394 if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) {
395
396 // find intersection point of edge and plane
397 dVector3 vIntersectionPoint;
398 vIntersectionPoint[0]= avArrayIn[i0][0] - (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
399 vIntersectionPoint[1]= avArrayIn[i0][1] - (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
400 vIntersectionPoint[2]= avArrayIn[i0][2] - (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
401
402 // emit intersection point
403 avArrayOut[ctOut][0] = vIntersectionPoint[0];
404 avArrayOut[ctOut][1] = vIntersectionPoint[1];
405 avArrayOut[ctOut][2] = vIntersectionPoint[2];
406 ctOut++;
407 }
408 }
409
410}
411
412
413
414
415static bool _cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
416 // reset best axis
417 iBestAxis = 0;
418 iExitAxis = -1;
419 fBestDepth = MAXVALUE;
420
421 // calculate edges
422 SUBTRACT(v1,v0,vE0);
423 SUBTRACT(v2,v0,vE1);
424 SUBTRACT(vE1,vE0,vE2);
425
426 // calculate poly normal
427 dCROSS(vN,=,vE0,vE1);
428
429 // extract box axes as vectors
430 dVector3 vA0,vA1,vA2;
431 GETCOL(mHullBoxRot,0,vA0);
432 GETCOL(mHullBoxRot,1,vA1);
433 GETCOL(mHullBoxRot,2,vA2);
434
435 // box halfsizes
436 dReal fa0 = vBoxHalfSize[0];
437 dReal fa1 = vBoxHalfSize[1];
438 dReal fa2 = vBoxHalfSize[2];
439
440 // calculate relative position between box and triangle
441 dVector3 vD;
442 SUBTRACT(v0,vHullBoxPos,vD);
443
444 // calculate length of face normal
445 dReal fNLen = LENGTHOF( vN );
446
447 dVector3 vL;
448 dReal fp0, fp1, fp2, fR, fD;
449
450 // Test separating axes for intersection
451 // ************************************************
452 // Axis 1 - Triangle Normal
453 SET(vL,vN);
454 fp0 = dDOT(vL,vD);
455 fp1 = fp0;
456 fp2 = fp0;
457 fR=fa0*dFabs( dDOT(vN,vA0) ) + fa1 * dFabs( dDOT(vN,vA1) ) + fa2 * dFabs( dDOT(vN,vA2) );
458
459
460 if( !_cldTestNormal( fp0, fR, vL, 1) ) {
461 iExitAxis=1;
462 return false;
463 }
464
465 // ************************************************
466
467 // Test Faces
468 // ************************************************
469 // Axis 2 - Box X-Axis
470 SET(vL,vA0);
471 fD = dDOT(vL,vN)/fNLen;
472 fp0 = dDOT(vL,vD);
473 fp1 = fp0 + dDOT(vA0,vE0);
474 fp2 = fp0 + dDOT(vA0,vE1);
475 fR = fa0;
476
477
478 if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 2) ) {
479 iExitAxis=2;
480 return false;
481 }
482 // ************************************************
483
484 // ************************************************
485 // Axis 3 - Box Y-Axis
486 SET(vL,vA1);
487 fD = dDOT(vL,vN)/fNLen;
488 fp0 = dDOT(vL,vD);
489 fp1 = fp0 + dDOT(vA1,vE0);
490 fp2 = fp0 + dDOT(vA1,vE1);
491 fR = fa1;
492
493
494 if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 3) ) {
495 iExitAxis=3;
496 return false;
497 }
498
499 // ************************************************
500
501 // ************************************************
502 // Axis 4 - Box Z-Axis
503 SET(vL,vA2);
504 fD = dDOT(vL,vN)/fNLen;
505 fp0 = dDOT(vL,vD);
506 fp1 = fp0 + dDOT(vA2,vE0);
507 fp2 = fp0 + dDOT(vA2,vE1);
508 fR = fa2;
509
510
511 if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 4) ) {
512 iExitAxis=4;
513 return false;
514 }
515
516 // ************************************************
517
518 // Test Edges
519 // ************************************************
520 // Axis 5 - Box X-Axis cross Edge0
521 dCROSS(vL,=,vA0,vE0);
522 fD = dDOT(vL,vN)/fNLen;
523 fp0 = dDOT(vL,vD);
524 fp1 = fp0;
525 fp2 = fp0 + dDOT(vA0,vN);
526 fR = fa1 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA1,vE0));
527
528
529 if( !_cldTestEdge( fp1, fp2, fR, fD, vL, 5) ) {
530 iExitAxis=5;
531 return false;
532 }
533 // ************************************************
534
535 // ************************************************
536 // Axis 6 - Box X-Axis cross Edge1
537 dCROSS(vL,=,vA0,vE1);
538 fD = dDOT(vL,vN)/fNLen;
539 fp0 = dDOT(vL,vD);
540 fp1 = fp0 - dDOT(vA0,vN);
541 fp2 = fp0;
542 fR = fa1 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA1,vE1));
543
544
545 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 6) ) {
546 iExitAxis=6;
547 return false;
548 }
549 // ************************************************
550
551 // ************************************************
552 // Axis 7 - Box X-Axis cross Edge2
553 dCROSS(vL,=,vA0,vE2);
554 fD = dDOT(vL,vN)/fNLen;
555 fp0 = dDOT(vL,vD);
556 fp1 = fp0 - dDOT(vA0,vN);
557 fp2 = fp0 - dDOT(vA0,vN);
558 fR = fa1 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA1,vE2));
559
560
561 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 7) ) {
562 iExitAxis=7;
563 return false;
564 }
565
566 // ************************************************
567
568 // ************************************************
569 // Axis 8 - Box Y-Axis cross Edge0
570 dCROSS(vL,=,vA1,vE0);
571 fD = dDOT(vL,vN)/fNLen;
572 fp0 = dDOT(vL,vD);
573 fp1 = fp0;
574 fp2 = fp0 + dDOT(vA1,vN);
575 fR = fa0 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA0,vE0));
576
577
578 if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 8) ) {
579 iExitAxis=8;
580 return false;
581 }
582
583 // ************************************************
584
585 // ************************************************
586 // Axis 9 - Box Y-Axis cross Edge1
587 dCROSS(vL,=,vA1,vE1);
588 fD = dDOT(vL,vN)/fNLen;
589 fp0 = dDOT(vL,vD);
590 fp1 = fp0 - dDOT(vA1,vN);
591 fp2 = fp0;
592 fR = fa0 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA0,vE1));
593
594
595 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 9) ) {
596 iExitAxis=9;
597 return false;
598 }
599
600 // ************************************************
601
602 // ************************************************
603 // Axis 10 - Box Y-Axis cross Edge2
604 dCROSS(vL,=,vA1,vE2);
605 fD = dDOT(vL,vN)/fNLen;
606 fp0 = dDOT(vL,vD);
607 fp1 = fp0 - dDOT(vA1,vN);
608 fp2 = fp0 - dDOT(vA1,vN);
609 fR = fa0 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA0,vE2));
610
611
612 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 10) ) {
613 iExitAxis=10;
614 return false;
615 }
616
617 // ************************************************
618
619 // ************************************************
620 // Axis 11 - Box Z-Axis cross Edge0
621 dCROSS(vL,=,vA2,vE0);
622 fD = dDOT(vL,vN)/fNLen;
623 fp0 = dDOT(vL,vD);
624 fp1 = fp0;
625 fp2 = fp0 + dDOT(vA2,vN);
626 fR = fa0 * dFabs(dDOT(vA1,vE0)) + fa1 * dFabs(dDOT(vA0,vE0));
627
628
629 if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 11) ) {
630 iExitAxis=11;
631 return false;
632 }
633 // ************************************************
634
635 // ************************************************
636 // Axis 12 - Box Z-Axis cross Edge1
637 dCROSS(vL,=,vA2,vE1);
638 fD = dDOT(vL,vN)/fNLen;
639 fp0 = dDOT(vL,vD);
640 fp1 = fp0 - dDOT(vA2,vN);
641 fp2 = fp0;
642 fR = fa0 * dFabs(dDOT(vA1,vE1)) + fa1 * dFabs(dDOT(vA0,vE1));
643
644
645 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 12) ) {
646 iExitAxis=12;
647 return false;
648 }
649 // ************************************************
650
651 // ************************************************
652 // Axis 13 - Box Z-Axis cross Edge2
653 dCROSS(vL,=,vA2,vE2);
654 fD = dDOT(vL,vN)/fNLen;
655 fp0 = dDOT(vL,vD);
656 fp1 = fp0 - dDOT(vA2,vN);
657 fp2 = fp0 - dDOT(vA2,vN);
658 fR = fa0 * dFabs(dDOT(vA1,vE2)) + fa1 * dFabs(dDOT(vA0,vE2));
659
660
661 if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 13) ) {
662 iExitAxis=13;
663 return false;
664 }
665
666 // ************************************************
667 return true;
668}
669
670
671
672
673
674// find two closest points on two lines
675static bool _cldClosestPointOnTwoLines( dVector3 vPoint1, dVector3 vLenVec1,
676 dVector3 vPoint2, dVector3 vLenVec2,
677 dReal &fvalue1, dReal &fvalue2)
678{
679 // calulate denominator
680 dVector3 vp;
681 SUBTRACT(vPoint2,vPoint1,vp);
682 dReal fuaub = dDOT(vLenVec1,vLenVec2);
683 dReal fq1 = dDOT(vLenVec1,vp);
684 dReal fq2 = -dDOT(vLenVec2,vp);
685 dReal fd = 1.0f - fuaub * fuaub;
686
687 // if denominator is positive
688 if (fd > 0.0f) {
689 // calculate points of closest approach
690 fd = 1.0f/fd;
691 fvalue1 = (fq1 + fuaub*fq2)*fd;
692 fvalue2 = (fuaub*fq1 + fq2)*fd;
693 return true;
694 // otherwise
695 } else {
696 // lines are parallel
697 fvalue1 = 0.0f;
698 fvalue2 = 0.0f;
699 return false;
700 }
701
702}
703
704
705
706
707
708// clip and generate contacts
709static void _cldClipping(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
710 dIASSERT( !(iFlags & CONTACTS_UNIMPORTANT) || ctContacts < (iFlags & NUMC_MASK) ); // Do not call the function if there is no room to store results
711
712 // if we have edge/edge intersection
713 if ( iBestAxis > 4 ) {
714
715 dVector3 vub,vPb,vPa;
716
717 SET(vPa,vHullBoxPos);
718
719 // calculate point on box edge
720 for( int i=0; i<3; i++) {
721 dVector3 vRotCol;
722 GETCOL(mHullBoxRot,i,vRotCol);
723 dReal fSign = dDOT(vBestNormal,vRotCol) > 0 ? 1.0f : -1.0f;
724
725 vPa[0] += fSign * vBoxHalfSize[i] * vRotCol[0];
726 vPa[1] += fSign * vBoxHalfSize[i] * vRotCol[1];
727 vPa[2] += fSign * vBoxHalfSize[i] * vRotCol[2];
728 }
729
730 int iEdge = (iBestAxis-5)%3;
731
732 // decide which edge is on triangle
733 if ( iEdge == 0 ) {
734 SET(vPb,v0);
735 SET(vub,vE0);
736 } else if ( iEdge == 1) {
737 SET(vPb,v2);
738 SET(vub,vE1);
739 } else {
740 SET(vPb,v1);
741 SET(vub,vE2);
742 }
743
744
745 // setup direction parameter for face edge
746 dNormalize3(vub);
747
748 dReal fParam1, fParam2;
749
750 // setup direction parameter for box edge
751 dVector3 vua;
752 int col=(iBestAxis-5)/3;
753 GETCOL(mHullBoxRot,col,vua);
754
755 // find two closest points on both edges
756 _cldClosestPointOnTwoLines( vPa, vua, vPb, vub, fParam1, fParam2 );
757 vPa[0] += vua[0]*fParam1;
758 vPa[1] += vua[1]*fParam1;
759 vPa[2] += vua[2]*fParam1;
760
761 vPb[0] += vub[0]*fParam2;
762 vPb[1] += vub[1]*fParam2;
763 vPb[2] += vub[2]*fParam2;
764
765 // calculate collision point
766 dVector3 vPntTmp;
767 ADD(vPa,vPb,vPntTmp);
768
769 vPntTmp[0]*=0.5f;
770 vPntTmp[1]*=0.5f;
771 vPntTmp[2]*=0.5f;
772
773 // generate contact point between two closest points
774#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
775 dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
776 Contact->depth = fBestDepth;
777 SET(Contact->normal,vBestNormal);
778 SET(Contact->pos,vPntTmp);
779 Contact->g1 = Geom1;
780 Contact->g2 = Geom2;
781 ctContacts++;
782#endif
783 GenerateContact(iFlags, ContactGeoms, iStride, Geom1, Geom2,
784 vPntTmp, vBestNormal, fBestDepth, ctContacts);
785
786
787 // if triangle is the referent face then clip box to triangle face
788 } else if ( iBestAxis == 1 ) {
789
790
791 dVector3 vNormal2;
792 vNormal2[0]=-vBestNormal[0];
793 vNormal2[1]=-vBestNormal[1];
794 vNormal2[2]=-vBestNormal[2];
795
796
797 // vNr is normal in box frame, pointing from triangle to box
798 dMatrix3 mTransposed;
799 mTransposed[0*4+0]=mHullBoxRot[0*4+0];
800 mTransposed[0*4+1]=mHullBoxRot[1*4+0];
801 mTransposed[0*4+2]=mHullBoxRot[2*4+0];
802
803 mTransposed[1*4+0]=mHullBoxRot[0*4+1];
804 mTransposed[1*4+1]=mHullBoxRot[1*4+1];
805 mTransposed[1*4+2]=mHullBoxRot[2*4+1];
806
807 mTransposed[2*4+0]=mHullBoxRot[0*4+2];
808 mTransposed[2*4+1]=mHullBoxRot[1*4+2];
809 mTransposed[2*4+2]=mHullBoxRot[2*4+2];
810
811 dVector3 vNr;
812 vNr[0]=mTransposed[0*4+0]*vNormal2[0]+ mTransposed[0*4+1]*vNormal2[1]+ mTransposed[0*4+2]*vNormal2[2];
813 vNr[1]=mTransposed[1*4+0]*vNormal2[0]+ mTransposed[1*4+1]*vNormal2[1]+ mTransposed[1*4+2]*vNormal2[2];
814 vNr[2]=mTransposed[2*4+0]*vNormal2[0]+ mTransposed[2*4+1]*vNormal2[1]+ mTransposed[2*4+2]*vNormal2[2];
815
816
817 dVector3 vAbsNormal;
818 vAbsNormal[0] = dFabs( vNr[0] );
819 vAbsNormal[1] = dFabs( vNr[1] );
820 vAbsNormal[2] = dFabs( vNr[2] );
821
822 // get closest face from box
823 int iB0, iB1, iB2;
824 if (vAbsNormal[1] > vAbsNormal[0]) {
825 if (vAbsNormal[1] > vAbsNormal[2]) {
826 iB1 = 0; iB0 = 1; iB2 = 2;
827 } else {
828 iB1 = 0; iB2 = 1; iB0 = 2;
829 }
830 } else {
831
832 if (vAbsNormal[0] > vAbsNormal[2]) {
833 iB0 = 0; iB1 = 1; iB2 = 2;
834 } else {
835 iB1 = 0; iB2 = 1; iB0 = 2;
836 }
837 }
838
839 // Here find center of box face we are going to project
840 dVector3 vCenter;
841 dVector3 vRotCol;
842 GETCOL(mHullBoxRot,iB0,vRotCol);
843
844 if (vNr[iB0] > 0) {
845 vCenter[0] = vHullBoxPos[0] - v0[0] - vBoxHalfSize[iB0] * vRotCol[0];
846 vCenter[1] = vHullBoxPos[1] - v0[1] - vBoxHalfSize[iB0] * vRotCol[1];
847 vCenter[2] = vHullBoxPos[2] - v0[2] - vBoxHalfSize[iB0] * vRotCol[2];
848 } else {
849 vCenter[0] = vHullBoxPos[0] - v0[0] + vBoxHalfSize[iB0] * vRotCol[0];
850 vCenter[1] = vHullBoxPos[1] - v0[1] + vBoxHalfSize[iB0] * vRotCol[1];
851 vCenter[2] = vHullBoxPos[2] - v0[2] + vBoxHalfSize[iB0] * vRotCol[2];
852 }
853
854 // Here find 4 corner points of box
855 dVector3 avPoints[4];
856
857 dVector3 vRotCol2;
858 GETCOL(mHullBoxRot,iB1,vRotCol);
859 GETCOL(mHullBoxRot,iB2,vRotCol2);
860
861 for(int x=0;x<3;x++) {
862 avPoints[0][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
863 avPoints[1][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
864 avPoints[2][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
865 avPoints[3][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
866 }
867
868
869 // clip Box face with 4 planes of triangle (1 face plane, 3 egde planes)
870 dVector3 avTempArray1[9];
871 dVector3 avTempArray2[9];
872 dVector4 plPlane;
873
874 int iTempCnt1=0;
875 int iTempCnt2=0;
876
877 // zeroify vectors - necessary?
878 for(int i=0; i<9; i++) {
879 avTempArray1[i][0]=0;
880 avTempArray1[i][1]=0;
881 avTempArray1[i][2]=0;
882
883 avTempArray2[i][0]=0;
884 avTempArray2[i][1]=0;
885 avTempArray2[i][2]=0;
886 }
887
888
889 // Normal plane
890 dVector3 vTemp;
891 vTemp[0]=-vN[0];
892 vTemp[1]=-vN[1];
893 vTemp[2]=-vN[2];
894 dNormalize3(vTemp);
895 CONSTRUCTPLANE(plPlane,vTemp,0);
896
897 _cldClipPolyToPlane( avPoints, 4, avTempArray1, iTempCnt1, plPlane );
898
899
900 // Plane p0
901 dVector3 vTemp2;
902 SUBTRACT(v1,v0,vTemp2);
903 dCROSS(vTemp,=,vN,vTemp2);
904 dNormalize3(vTemp);
905 CONSTRUCTPLANE(plPlane,vTemp,0);
906
907 _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
908
909
910 // Plane p1
911 SUBTRACT(v2,v1,vTemp2);
912 dCROSS(vTemp,=,vN,vTemp2);
913 dNormalize3(vTemp);
914 SUBTRACT(v0,v2,vTemp2);
915 CONSTRUCTPLANE(plPlane,vTemp,dDOT(vTemp2,vTemp));
916
917 _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane );
918
919
920 // Plane p2
921 SUBTRACT(v0,v2,vTemp2);
922 dCROSS(vTemp,=,vN,vTemp2);
923 dNormalize3(vTemp);
924 CONSTRUCTPLANE(plPlane,vTemp,0);
925
926 _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
927
928
929 // END of clipping polygons
930
931
932
933 // for each generated contact point
934 for ( int i=0; i<iTempCnt2; i++ ) {
935 // calculate depth
936 dReal fTempDepth = dDOT(vNormal2,avTempArray2[i]);
937
938 // clamp depth to zero
939 if (fTempDepth > 0) {
940 fTempDepth = 0;
941 }
942
943 dVector3 vPntTmp;
944 ADD(avTempArray2[i],v0,vPntTmp);
945
946#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
947 dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
948
949 Contact->depth = -fTempDepth;
950 SET(Contact->normal,vBestNormal);
951 SET(Contact->pos,vPntTmp);
952 Contact->g1 = Geom1;
953 Contact->g2 = Geom2;
954 ctContacts++;
955#endif
956 GenerateContact(iFlags, ContactGeoms, iStride, Geom1, Geom2,
957 vPntTmp, vBestNormal, -fTempDepth, ctContacts);
958
959 if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
960 break;
961 }
962 }
963
964 //dAASSERT(ctContacts>0);
965
966 // if box face is the referent face, then clip triangle on box face
967 } else { // 2 <= if iBestAxis <= 4
968
969 // get normal of box face
970 dVector3 vNormal2;
971 SET(vNormal2,vBestNormal);
972
973 // get indices of box axes in correct order
974 int iA0,iA1,iA2;
975 iA0 = iBestAxis-2;
976 if ( iA0 == 0 ) {
977 iA1 = 1; iA2 = 2;
978 } else if ( iA0 == 1 ) {
979 iA1 = 0; iA2 = 2;
980 } else {
981 iA1 = 0; iA2 = 1;
982 }
983
984 dVector3 avPoints[3];
985 // calculate triangle vertices in box frame
986 SUBTRACT(v0,vHullBoxPos,avPoints[0]);
987 SUBTRACT(v1,vHullBoxPos,avPoints[1]);
988 SUBTRACT(v2,vHullBoxPos,avPoints[2]);
989
990 // CLIP Polygons
991 // define temp data for clipping
992 dVector3 avTempArray1[9];
993 dVector3 avTempArray2[9];
994
995 int iTempCnt1, iTempCnt2;
996
997 // zeroify vectors - necessary?
998 for(int i=0; i<9; i++) {
999 avTempArray1[i][0]=0;
1000 avTempArray1[i][1]=0;
1001 avTempArray1[i][2]=0;
1002
1003 avTempArray2[i][0]=0;
1004 avTempArray2[i][1]=0;
1005 avTempArray2[i][2]=0;
1006 }
1007
1008 // clip triangle with 5 box planes (1 face plane, 4 edge planes)
1009
1010 dVector4 plPlane;
1011
1012 // Normal plane
1013 dVector3 vTemp;
1014 vTemp[0]=-vNormal2[0];
1015 vTemp[1]=-vNormal2[1];
1016 vTemp[2]=-vNormal2[2];
1017 CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA0]);
1018
1019 _cldClipPolyToPlane( avPoints, 3, avTempArray1, iTempCnt1, plPlane );
1020
1021
1022 // Plane p0
1023 GETCOL(mHullBoxRot,iA1,vTemp);
1024 CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA1]);
1025
1026 _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
1027
1028
1029 // Plane p1
1030 GETCOL(mHullBoxRot,iA1,vTemp);
1031 vTemp[0]=-vTemp[0];
1032 vTemp[1]=-vTemp[1];
1033 vTemp[2]=-vTemp[2];
1034 CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA1]);
1035
1036 _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane );
1037
1038
1039 // Plane p2
1040 GETCOL(mHullBoxRot,iA2,vTemp);
1041 CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA2]);
1042
1043 _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
1044
1045
1046 // Plane p3
1047 GETCOL(mHullBoxRot,iA2,vTemp);
1048 vTemp[0]=-vTemp[0];
1049 vTemp[1]=-vTemp[1];
1050 vTemp[2]=-vTemp[2];
1051 CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA2]);
1052
1053 _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane );
1054
1055
1056 // for each generated contact point
1057 for ( int i=0; i<iTempCnt1; i++ ) {
1058 // calculate depth
1059 dReal fTempDepth = dDOT(vNormal2,avTempArray1[i])-vBoxHalfSize[iA0];
1060
1061 // clamp depth to zero
1062 if (fTempDepth > 0) {
1063 fTempDepth = 0;
1064 }
1065
1066 // generate contact data
1067 dVector3 vPntTmp;
1068 ADD(avTempArray1[i],vHullBoxPos,vPntTmp);
1069
1070#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
1071 dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
1072
1073 Contact->depth = -fTempDepth;
1074 SET(Contact->normal,vBestNormal);
1075 SET(Contact->pos,vPntTmp);
1076 Contact->g1 = Geom1;
1077 Contact->g2 = Geom2;
1078 ctContacts++;
1079#endif
1080 GenerateContact(iFlags, ContactGeoms, iStride, Geom1, Geom2,
1081 vPntTmp, vBestNormal, -fTempDepth, ctContacts);
1082
1083 if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
1084 break;
1085 }
1086 }
1087
1088 //dAASSERT(ctContacts>0);
1089 }
1090
1091}
1092
1093
1094
1095
1096
1097// test one mesh triangle on intersection with given box
1098static void _cldTestOneTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)//, void *pvUser)
1099{
1100 // do intersection test and find best separating axis
1101 if(!_cldTestSeparatingAxes(v0, v1, v2) ) {
1102 // if not found do nothing
1103 return;
1104 }
1105
1106 // if best separation axis is not found
1107 if ( iBestAxis == 0 ) {
1108 // this should not happen (we should already exit in that case)
1109 //dMessage (0, "best separation axis not found");
1110 // do nothing
1111 return;
1112 }
1113
1114 _cldClipping(v0, v1, v2);
1115}
1116
1117
1118
1119
1120
1121// OPCODE version of box to mesh collider
1122#if dTRIMESH_OPCODE
1123int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride){
1124 dIASSERT (Stride >= (int)sizeof(dContactGeom));
1125 dIASSERT (g1->type == dTriMeshClass);
1126 dIASSERT (BoxGeom->type == dBoxClass);
1127 dIASSERT ((Flags & NUMC_MASK) >= 1);
1128
1129
1130 dxTriMesh* TriMesh = (dxTriMesh*)g1;
1131
1132
1133 // get source hull position, orientation and half size
1134 const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom);
1135 const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom);
1136
1137 // to global
1138 SETM(mHullBoxRot,mRotBox);
1139 SET(vHullBoxPos,vPosBox);
1140
1141 dGeomBoxGetLengths(BoxGeom, vBoxHalfSize);
1142 vBoxHalfSize[0] *= 0.5f;
1143 vBoxHalfSize[1] *= 0.5f;
1144 vBoxHalfSize[2] *= 0.5f;
1145
1146
1147
1148 // get destination hull position and orientation
1149 const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh);
1150 const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh);
1151
1152 // to global
1153 SET(vHullDstPos,vPosMesh);
1154
1155
1156
1157 // global info for contact creation
1158 ctContacts = 0;
1159 iStride=Stride;
1160 iFlags=Flags;
1161 ContactGeoms=Contacts;
1162 Geom1=TriMesh;
1163 Geom2=BoxGeom;
1164
1165
1166
1167 // reset stuff
1168 fBestDepth = MAXVALUE;
1169 vBestNormal[0]=0;
1170 vBestNormal[1]=0;
1171 vBestNormal[2]=0;
1172
1173 OBBCollider& Collider = TriMesh->_OBBCollider;
1174
1175
1176
1177
1178 // Make OBB
1179 OBB Box;
1180 Box.mCenter.x = vPosBox[0];
1181 Box.mCenter.y = vPosBox[1];
1182 Box.mCenter.z = vPosBox[2];
1183
1184 // It is a potential issue to explicitly cast to float
1185 // if custom width floating point type is introduced in OPCODE.
1186 // It is necessary to make a typedef and cast to it
1187 // (e.g. typedef float opc_float;)
1188 // However I'm not sure in what header it should be added.
1189
1190 Box.mExtents.x = /*(float)*/vBoxHalfSize[0];
1191 Box.mExtents.y = /*(float)*/vBoxHalfSize[1];
1192 Box.mExtents.z = /*(float)*/vBoxHalfSize[2];
1193
1194 Box.mRot.m[0][0] = /*(float)*/mRotBox[0];
1195 Box.mRot.m[1][0] = /*(float)*/mRotBox[1];
1196 Box.mRot.m[2][0] = /*(float)*/mRotBox[2];
1197
1198 Box.mRot.m[0][1] = /*(float)*/mRotBox[4];
1199 Box.mRot.m[1][1] = /*(float)*/mRotBox[5];
1200 Box.mRot.m[2][1] = /*(float)*/mRotBox[6];
1201
1202 Box.mRot.m[0][2] = /*(float)*/mRotBox[8];
1203 Box.mRot.m[1][2] = /*(float)*/mRotBox[9];
1204 Box.mRot.m[2][2] = /*(float)*/mRotBox[10];
1205
1206 Matrix4x4 amatrix;
1207 Matrix4x4 BoxMatrix = MakeMatrix(vPosBox, mRotBox, amatrix);
1208
1209 Matrix4x4 InvBoxMatrix;
1210 InvertPRMatrix(InvBoxMatrix, BoxMatrix);
1211
1212 // TC results
1213 if (TriMesh->doBoxTC) {
1214 dxTriMesh::BoxTC* BoxTC = 0;
1215 for (int i = 0; i < TriMesh->BoxTCCache.size(); i++){
1216 if (TriMesh->BoxTCCache[i].Geom == BoxGeom){
1217 BoxTC = &TriMesh->BoxTCCache[i];
1218 break;
1219 }
1220 }
1221 if (!BoxTC){
1222 TriMesh->BoxTCCache.push(dxTriMesh::BoxTC());
1223
1224 BoxTC = &TriMesh->BoxTCCache[TriMesh->BoxTCCache.size() - 1];
1225 BoxTC->Geom = BoxGeom;
1226 BoxTC->FatCoeff = 1.1f; // Pierre recommends this, instead of 1.0
1227 }
1228
1229 // Intersect
1230 Collider.SetTemporalCoherence(true);
1231 Collider.Collide(*BoxTC, Box, TriMesh->Data->BVTree, null, &MakeMatrix(vPosMesh, mRotMesh, amatrix));
1232 }
1233 else {
1234 Collider.SetTemporalCoherence(false);
1235 Collider.Collide(dxTriMesh::defaultBoxCache, Box, TriMesh->Data->BVTree, null,
1236 &MakeMatrix(vPosMesh, mRotMesh, amatrix));
1237 }
1238
1239 if (! Collider.GetContactStatus()) {
1240 // no collision occurred
1241 return 0;
1242 }
1243
1244 // Retrieve data
1245 int TriCount = Collider.GetNbTouchedPrimitives();
1246 const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
1247
1248 if (TriCount != 0){
1249 if (TriMesh->ArrayCallback != null){
1250 TriMesh->ArrayCallback(TriMesh, BoxGeom, Triangles, TriCount);
1251 }
1252
1253 int ctContacts0 = 0;
1254
1255 // loop through all intersecting triangles
1256 for (int i = 0; i < TriCount; i++){
1257
1258
1259 const int Triint = Triangles[i];
1260 if (!Callback(TriMesh, BoxGeom, Triint)) continue;
1261
1262
1263 dVector3 dv[3];
1264 FetchTriangle(TriMesh, Triint, vPosMesh, mRotMesh, dv);
1265
1266
1267 // test this triangle
1268 _cldTestOneTriangle(dv[0],dv[1],dv[2]);
1269
1270 // fill-in tri index for generated contacts
1271 for (; ctContacts0<ctContacts; ctContacts0++)
1272 SAFECONTACT(iFlags, ContactGeoms, ctContacts0, iStride)->side1 = Triint;
1273
1274 /*
1275 NOTE by Oleh_Derevenko:
1276 The function continues checking triangles after maximal number
1277 of contacts is reached because it selects maximal penetration depths.
1278 See also comments in GenerateContact()
1279 */
1280 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
1281 if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
1282 break;
1283 }
1284 }
1285
1286
1287 return ctContacts;
1288}
1289#endif
1290
1291// GIMPACT version of box to mesh collider
1292#if dTRIMESH_GIMPACT
1293int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride)
1294{
1295 dIASSERT (Stride >= (int)sizeof(dContactGeom));
1296 dIASSERT (g1->type == dTriMeshClass);
1297 dIASSERT (BoxGeom->type == dBoxClass);
1298 dIASSERT ((Flags & NUMC_MASK) >= 1);
1299
1300
1301 dxTriMesh* TriMesh = (dxTriMesh*)g1;
1302
1303
1304 // get source hull position, orientation and half size
1305 const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom);
1306 const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom);
1307
1308 // to global
1309 SETM(mHullBoxRot,mRotBox);
1310 SET(vHullBoxPos,vPosBox);
1311
1312 dGeomBoxGetLengths(BoxGeom, vBoxHalfSize);
1313 vBoxHalfSize[0] *= 0.5f;
1314 vBoxHalfSize[1] *= 0.5f;
1315 vBoxHalfSize[2] *= 0.5f;
1316
1317 // get destination hull position and orientation
1318 /*const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh);
1319 const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh);
1320
1321 // to global
1322 SET(vHullDstPos,vPosMesh);*/
1323
1324 // global info for contact creation
1325 ctContacts = 0;
1326 iStride=Stride;
1327 iFlags=Flags;
1328 ContactGeoms=Contacts;
1329 Geom1=TriMesh;
1330 Geom2=BoxGeom;
1331
1332
1333 // reset stuff
1334 fBestDepth = MAXVALUE;
1335 vBestNormal[0]=0;
1336 vBestNormal[1]=0;
1337 vBestNormal[2]=0;
1338
1339
1340//*****at first , collide box aabb******//
1341
1342 GIM_TRIMESH * ptrimesh = &TriMesh->m_collision_trimesh;
1343 aabb3f test_aabb;
1344
1345 test_aabb.minX = BoxGeom->aabb[0];
1346 test_aabb.maxX = BoxGeom->aabb[1];
1347 test_aabb.minY = BoxGeom->aabb[2];
1348 test_aabb.maxY = BoxGeom->aabb[3];
1349 test_aabb.minZ = BoxGeom->aabb[4];
1350 test_aabb.maxZ = BoxGeom->aabb[5];
1351
1352 GDYNAMIC_ARRAY collision_result;
1353 GIM_CREATE_BOXQUERY_LIST(collision_result);
1354
1355 gim_aabbset_box_collision(&test_aabb, &ptrimesh->m_aabbset , &collision_result);
1356
1357 if(collision_result.m_size==0)
1358 {
1359 GIM_DYNARRAY_DESTROY(collision_result);
1360 return 0;
1361 }
1362//*****Set globals for box collision******//
1363
1364 //collide triangles
1365
1366 GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
1367 gim_trimesh_locks_work_data(ptrimesh);
1368
1369 int ctContacts0 = 0;
1370
1371 for(unsigned int i=0;i<collision_result.m_size;i++)
1372 {
1373 dVector3 dv[3];
1374
1375 int Triint = boxesresult[i];
1376 gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]);
1377 // test this triangle
1378 _cldTestOneTriangle(dv[0],dv[1],dv[2]);
1379
1380 // fill-in tri index for generated contacts
1381 for (; ctContacts0<ctContacts; ctContacts0++)
1382 SAFECONTACT(iFlags, ContactGeoms, ctContacts0, iStride)->side1 = Triint;
1383
1384 /*
1385 NOTE by Oleh_Derevenko:
1386 The function continues checking triangles after maximal number
1387 of contacts is reached because it selects maximal penetration depths.
1388 See also comments in GenerateContact()
1389 */
1390 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
1391 if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
1392 break;
1393 }
1394
1395 gim_trimesh_unlocks_work_data(ptrimesh);
1396 GIM_DYNARRAY_DESTROY(collision_result);
1397
1398 return ctContacts;
1399}
1400#endif
1401
1402
1403// GenerateContact - Written by Jeff Smith (jeff@burri.to)
1404// Generate a "unique" contact. A unique contact has a unique
1405// position or normal. If the potential contact has the same
1406// position and normal as an existing contact, but a larger
1407// penetration depth, this new depth is used instead
1408//
1409static void
1410GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,
1411 dxGeom* in_g1, dxGeom* in_g2,
1412 const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
1413 int& OutTriCount)
1414{
1415 /*
1416 NOTE by Oleh_Derevenko:
1417 This function is called after maximal number of contacts has already been
1418 collected because it has a side effect of replacing penetration depth of
1419 existing contact with larger penetration depth of another matching normal contact.
1420 If this logic is not necessary any more, you can bail out on reach of contact
1421 number maximum immediately in dCollideBTL(). You will also need to correct
1422 conditional statements after invocations of GenerateContact() in _cldClipping().
1423 */
1424 do
1425 {
1426 dContactGeom* Contact;
1427 dVector3 diff;
1428
1429 if (!(in_Flags & CONTACTS_UNIMPORTANT))
1430 {
1431 bool duplicate = false;
1432 for (int i=0; i<OutTriCount; i++)
1433 {
1434 Contact = SAFECONTACT(in_Flags, in_Contacts, i, in_Stride);
1435
1436 // same position?
1437 for (int j=0; j<3; j++)
1438 diff[j] = in_ContactPos[j] - Contact->pos[j];
1439 if (dDOT(diff, diff) < dEpsilon)
1440 {
1441 // same normal?
1442 if (dFabs(dDOT(in_Normal, Contact->normal)) > (REAL(1.0)-dEpsilon))
1443 {
1444 if (in_Depth > Contact->depth)
1445 Contact->depth = in_Depth;
1446 duplicate = true;
1447 /*
1448 NOTE by Oleh_Derevenko:
1449 There may be a case when two normals are close to each other but not duplicate
1450 while third normal is detected to be duplicate for both of them.
1451 This is the only reason I can think of, there is no "break" statement.
1452 Perhaps author considered it to be logical that the third normal would
1453 replace the depth in both of initial contacts.
1454 However, I consider it a questionable practice which should not
1455 be applied without deep understanding of underlaying physics.
1456 Even more, is this situation with close normal triplet acceptable at all?
1457 Should not be two initial contacts reduced to one (replaced with the latter)?
1458 If you know the answers for these questions, you may want to change this code.
1459 See the same statement in GenerateContact() of collision_trimesh_trimesh.cpp
1460 */
1461 }
1462 }
1463 }
1464 if (duplicate || OutTriCount == (in_Flags & NUMC_MASK))
1465 {
1466 break;
1467 }
1468 }
1469 else
1470 {
1471 dIASSERT(OutTriCount < (in_Flags & NUMC_MASK));
1472 }
1473
1474 // Add a new contact
1475 Contact = SAFECONTACT(in_Flags, in_Contacts, OutTriCount, in_Stride);
1476
1477 Contact->pos[0] = in_ContactPos[0];
1478 Contact->pos[1] = in_ContactPos[1];
1479 Contact->pos[2] = in_ContactPos[2];
1480 Contact->pos[3] = 0.0;
1481
1482 Contact->normal[0] = in_Normal[0];
1483 Contact->normal[1] = in_Normal[1];
1484 Contact->normal[2] = in_Normal[2];
1485 Contact->normal[3] = 0.0;
1486
1487 Contact->depth = in_Depth;
1488
1489 Contact->g1 = in_g1;
1490 Contact->g2 = in_g2;
1491
1492 OutTriCount++;
1493 }
1494 while (false);
1495}
1496
1497#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp
deleted file mode 100644
index da235e0..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp
+++ /dev/null
@@ -1,1181 +0,0 @@
1/*************************************************************************
2* *
3* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4* All rights reserved. Email: russ@q12.org Web: www.q12.org *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of EITHER: *
8* (1) The GNU Lesser General Public License as published by the Free *
9* Software Foundation; either version 2.1 of the License, or (at *
10* your option) any later version. The text of the GNU Lesser *
11* General Public License is included with this library in the *
12* file LICENSE.TXT. *
13* (2) The BSD-style license that is included with this library in *
14* the file LICENSE-BSD.TXT. *
15* *
16* This library is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20* *
21*************************************************************************/
22
23/*
24 * Triangle-Capsule(Capsule) collider by Alen Ladavac
25 * Ported to ODE by Nguyen Binh
26 */
27
28// NOTES from Nguyen Binh
29// 14 Apr : Seem to be robust
30// There is a problem when you use original Step and set contact friction
31// surface.mu = dInfinity;
32// More description :
33// When I dropped Capsule over the bunny ears, it seems to stuck
34// there for a while. I think the cause is when you set surface.mu = dInfinity;
35// the friction force is too high so it just hang the capsule there.
36// So the good cure for this is to set mu = around 1.5 (in my case)
37// For StepFast1, this become as solid as rock : StepFast1 just approximate
38// friction force.
39
40// NOTES from Croteam's Alen
41//As a side note... there are some extra contacts that can be generated
42//on the edge between two triangles, and if the capsule penetrates deeply into
43//the triangle (usually happens with large mass or low FPS), some such
44//contacts can in some cases push the capsule away from the edge instead of
45//away from the two triangles. This shows up as capsule slowing down a bit
46//when hitting an edge while sliding along a flat tesselated grid of
47//triangles. This is only if capsule is standing upwards.
48
49//Same thing can appear whenever a smooth object (e.g sphere) hits such an
50//edge, and it needs to be solved as a special case probably. This is a
51//problem we are looking forward to address soon.
52
53#include <ode/collision.h>
54#include <ode/matrix.h>
55#include <ode/rotation.h>
56#include <ode/odemath.h>
57#include "collision_util.h"
58
59#define TRIMESH_INTERNAL
60#include "collision_trimesh_internal.h"
61
62#if dTRIMESH_ENABLED
63
64// OPCODE version
65#if dTRIMESH_OPCODE
66// largest number, double or float
67#if defined(dSINGLE)
68#define MAX_REAL FLT_MAX
69#define MIN_REAL (-FLT_MAX)
70#else
71#define MAX_REAL DBL_MAX
72#define MIN_REAL (-DBL_MAX)
73#endif
74
75// To optimize before send contacts to dynamic part
76#define OPTIMIZE_CONTACTS
77
78// dVector3
79// r=a-b
80#define SUBTRACT(a,b,r) \
81 (r)[0]=(a)[0] - (b)[0]; \
82 (r)[1]=(a)[1] - (b)[1]; \
83 (r)[2]=(a)[2] - (b)[2];
84
85
86// dVector3
87// a=b
88#define SET(a,b) \
89 (a)[0]=(b)[0]; \
90 (a)[1]=(b)[1]; \
91 (a)[2]=(b)[2];
92
93
94// dMatrix3
95// a=b
96#define SETM(a,b) \
97 (a)[0]=(b)[0]; \
98 (a)[1]=(b)[1]; \
99 (a)[2]=(b)[2]; \
100 (a)[3]=(b)[3]; \
101 (a)[4]=(b)[4]; \
102 (a)[5]=(b)[5]; \
103 (a)[6]=(b)[6]; \
104 (a)[7]=(b)[7]; \
105 (a)[8]=(b)[8]; \
106 (a)[9]=(b)[9]; \
107 (a)[10]=(b)[10]; \
108 (a)[11]=(b)[11];
109
110
111// dVector3
112// r=a+b
113#define ADD(a,b,r) \
114 (r)[0]=(a)[0] + (b)[0]; \
115 (r)[1]=(a)[1] + (b)[1]; \
116 (r)[2]=(a)[2] + (b)[2];
117
118
119// dMatrix3, int, dVector3
120// v=column a from m
121#define GETCOL(m,a,v) \
122 (v)[0]=(m)[(a)+0]; \
123 (v)[1]=(m)[(a)+4]; \
124 (v)[2]=(m)[(a)+8];
125
126
127// dVector4, dVector3
128// distance between plane p and point v
129#define POINTDISTANCE(p,v) \
130 ( p[0]*v[0] + p[1]*v[1] + p[2]*v[2] + p[3] ); \
131
132
133// dVector4, dVector3, dReal
134// construct plane from normal and d
135#define CONSTRUCTPLANE(plane,normal,d) \
136 plane[0]=normal[0];\
137 plane[1]=normal[1];\
138 plane[2]=normal[2];\
139 plane[3]=d;
140
141
142// dVector3
143// length of vector a
144#define LENGTHOF(a) \
145 dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);\
146
147inline dReal _length2OfVector3(dVector3 v)
148{
149 return (v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
150}
151
152
153// Local contacts data
154typedef struct _sLocalContactData
155{
156 dVector3 vPos;
157 dVector3 vNormal;
158 dReal fDepth;
159 int triIndex;
160 int nFlags; // 0 = filtered out, 1 = OK
161}sLocalContactData;
162
163static sLocalContactData *gLocalContacts;
164static unsigned int ctContacts = 0;
165
166// capsule data
167// real time data
168static dMatrix3 mCapsuleRotation;
169static dVector3 vCapsulePosition;
170static dVector3 vCapsuleAxis;
171// static data
172static dReal vCapsuleRadius;
173static dReal fCapsuleSize;
174
175// mesh data
176static dMatrix4 mHullDstPl;
177static dMatrix3 mTriMeshRot;
178static dVector3 mTriMeshPos;
179static dVector3 vE0, vE1, vE2;
180
181// Two geom
182dxGeom* gCylinder;
183dxGeom* gTriMesh;
184
185// global collider data
186static dVector3 vNormal;
187static dReal fBestDepth;
188static dReal fBestCenter;
189static dReal fBestrt;
190static int iBestAxis;
191static dVector3 vN = {0,0,0,0};
192
193static dVector3 vV0;
194static dVector3 vV1;
195static dVector3 vV2;
196
197// ODE contact's specific
198static unsigned int iFlags;
199static dContactGeom *ContactGeoms;
200static int iStride;
201
202// Capsule lie on axis number 3 = (Z axis)
203static const int nCAPSULE_AXIS = 2;
204
205// Use to classify contacts to be "near" in position
206static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4
207// Use to classify contacts to be "near" in normal direction
208static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4
209
210
211// If this two contact can be classified as "near"
212inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2)
213{
214 int bPosNear = 0;
215 int bSameDir = 0;
216 dVector3 vDiff;
217
218 // First check if they are "near" in position
219 SUBTRACT(c1.vPos,c2.vPos,vDiff);
220 if ( (dFabs(vDiff[0]) < fSameContactPositionEpsilon)
221 &&(dFabs(vDiff[1]) < fSameContactPositionEpsilon)
222 &&(dFabs(vDiff[2]) < fSameContactPositionEpsilon))
223 {
224 bPosNear = 1;
225 }
226
227 // Second check if they are "near" in normal direction
228 SUBTRACT(c1.vNormal,c2.vNormal,vDiff);
229 if ( (dFabs(vDiff[0]) < fSameContactNormalEpsilon)
230 &&(dFabs(vDiff[1]) < fSameContactNormalEpsilon)
231 &&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) )
232 {
233 bSameDir = 1;
234 }
235
236 // Will be "near" if position and normal direction are "near"
237 return (bPosNear && bSameDir);
238}
239
240inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2)
241{
242 // The not better will be throw away
243 // You can change the selection criteria here
244 return (c1.fDepth > c2.fDepth);
245}
246
247// iterate through gLocalContacts and filtered out "near contact"
248inline void _OptimizeLocalContacts()
249{
250 int nContacts = ctContacts;
251
252 for (int i = 0; i < nContacts-1; i++)
253 {
254 for (int j = i+1; j < nContacts; j++)
255 {
256 if (_IsNearContacts(gLocalContacts[i],gLocalContacts[j]))
257 {
258 // If they are seem to be the samed then filtered
259 // out the least penetrate one
260 if (_IsBetter(gLocalContacts[j],gLocalContacts[i]))
261 {
262 gLocalContacts[i].nFlags = 0; // filtered 1st contact
263 }
264 else
265 {
266 gLocalContacts[j].nFlags = 0; // filtered 2nd contact
267 }
268
269 // NOTE
270 // There is other way is to add two depth together but
271 // it not work so well. Why???
272 }
273 }
274 }
275}
276
277inline int _ProcessLocalContacts()
278{
279 if (ctContacts == 0)
280 {
281 return 0;
282 }
283
284#ifdef OPTIMIZE_CONTACTS
285 if (ctContacts > 1 && !(iFlags & CONTACTS_UNIMPORTANT))
286 {
287 // Can be optimized...
288 _OptimizeLocalContacts();
289 }
290#endif
291
292 unsigned int iContact = 0;
293 dContactGeom* Contact = 0;
294
295 unsigned int nFinalContact = 0;
296
297 for (iContact = 0; iContact < ctContacts; iContact ++)
298 {
299 // Ensure that we haven't created too many contacts
300 if( nFinalContact >= (iFlags & NUMC_MASK))
301 {
302 break;
303 }
304
305 if (1 == gLocalContacts[iContact].nFlags)
306 {
307 Contact = SAFECONTACT(iFlags, ContactGeoms, nFinalContact, iStride);
308 Contact->depth = gLocalContacts[iContact].fDepth;
309 SET(Contact->normal,gLocalContacts[iContact].vNormal);
310 SET(Contact->pos,gLocalContacts[iContact].vPos);
311 Contact->g1 = gTriMesh;
312 Contact->g2 = gCylinder;
313 Contact->side2 = gLocalContacts[iContact].triIndex;
314
315 nFinalContact++;
316 }
317 }
318 // debug
319 //if (nFinalContact != ctContacts)
320 //{
321 // printf("[Info] %d contacts generated,%d filtered.\n",ctContacts,ctContacts-nFinalContact);
322 //}
323
324 return nFinalContact;
325}
326
327BOOL _cldClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane)
328{
329 // calculate distance of edge points to plane
330 dReal fDistance0 = POINTDISTANCE( plPlane, vEpnt0 );
331 dReal fDistance1 = POINTDISTANCE( plPlane, vEpnt1 );
332
333 // if both points are behind the plane
334 if ( fDistance0 < 0 && fDistance1 < 0 )
335 {
336 // do nothing
337 return FALSE;
338 // if both points in front of the plane
339 } else if ( fDistance0 > 0 && fDistance1 > 0 )
340 {
341 // accept them
342 return TRUE;
343 // if we have edge/plane intersection
344 } else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0))
345 {
346
347 // find intersection point of edge and plane
348 dVector3 vIntersectionPoint;
349 vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1);
350 vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1);
351 vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1);
352
353 // clamp correct edge to intersection point
354 if ( fDistance0 < 0 )
355 {
356 SET(vEpnt0,vIntersectionPoint);
357 } else
358 {
359 SET(vEpnt1,vIntersectionPoint);
360 }
361 return TRUE;
362 }
363 return TRUE;
364}
365
366static BOOL _cldTestAxis(const dVector3 &v0,
367 const dVector3 &v1,
368 const dVector3 &v2,
369 dVector3 vAxis,
370 int iAxis,
371 BOOL bNoFlip = FALSE)
372{
373
374 // calculate length of separating axis vector
375 dReal fL = LENGTHOF(vAxis);
376 // if not long enough
377 // TODO : dReal epsilon please
378 if ( fL < REAL(1e-5) )
379 {
380 // do nothing
381 //iLastOutAxis = 0;
382 return TRUE;
383 }
384
385 // otherwise normalize it
386 dNormalize3(vAxis);
387
388 // project capsule on vAxis
389 dReal frc = dFabs(dDOT(vCapsuleAxis,vAxis))*(fCapsuleSize*REAL(0.5)-vCapsuleRadius) + vCapsuleRadius;
390
391 // project triangle on vAxis
392 dReal afv[3];
393 afv[0] = dDOT( vV0 , vAxis );
394 afv[1] = dDOT( vV1 , vAxis );
395 afv[2] = dDOT( vV2 , vAxis );
396
397 dReal fMin = MAX_REAL;
398 dReal fMax = MIN_REAL;
399
400 // for each vertex
401 for(int i=0; i<3; i++)
402 {
403 // find minimum
404 if (afv[i]<fMin)
405 {
406 fMin = afv[i];
407 }
408 // find maximum
409 if (afv[i]>fMax)
410 {
411 fMax = afv[i];
412 }
413 }
414
415 // find triangle's center of interval on axis
416 dReal fCenter = (fMin+fMax)*REAL(0.5);
417 // calculate triangles half interval
418 dReal fTriangleRadius = (fMax-fMin)*REAL(0.5);
419
420 // if they do not overlap,
421 if( dFabs(fCenter) > ( frc + fTriangleRadius ) )
422 {
423 // exit, we have no intersection
424 return FALSE;
425 }
426
427 // calculate depth
428 dReal fDepth = dFabs(fCenter) - (frc+fTriangleRadius);
429
430 // if greater then best found so far
431 if ( fDepth > fBestDepth )
432 {
433 // remember depth
434 fBestDepth = fDepth;
435 fBestCenter = fCenter;
436 fBestrt = fTriangleRadius;
437
438 vNormal[0] = vAxis[0];
439 vNormal[1] = vAxis[1];
440 vNormal[2] = vAxis[2];
441
442 iBestAxis = iAxis;
443
444 // flip normal if interval is wrong faced
445 if (fCenter<0 && !bNoFlip)
446 {
447 vNormal[0] = -vNormal[0];
448 vNormal[1] = -vNormal[1];
449 vNormal[2] = -vNormal[2];
450
451 fBestCenter = -fCenter;
452 }
453 }
454
455 return TRUE;
456}
457
458// helper for less key strokes
459inline void _CalculateAxis(const dVector3& v1,
460 const dVector3& v2,
461 const dVector3& v3,
462 const dVector3& v4,
463 dVector3& r)
464{
465 dVector3 t1;
466 dVector3 t2;
467
468 SUBTRACT(v1,v2,t1);
469 dCROSS(t2,=,t1,v3);
470 dCROSS(r,=,t2,v4);
471}
472
473static BOOL _cldTestSeparatingAxesOfCapsule(const dVector3 &v0,
474 const dVector3 &v1,
475 const dVector3 &v2,
476 uint8 flags)
477{
478 // calculate caps centers in absolute space
479 dVector3 vCp0;
480 vCp0[0] = vCapsulePosition[0] + vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
481 vCp0[1] = vCapsulePosition[1] + vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
482 vCp0[2] = vCapsulePosition[2] + vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
483
484 dVector3 vCp1;
485 vCp1[0] = vCapsulePosition[0] - vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
486 vCp1[1] = vCapsulePosition[1] - vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
487 vCp1[2] = vCapsulePosition[2] - vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
488
489 // reset best axis
490 iBestAxis = 0;
491 // reset best depth
492 fBestDepth = -MAX_REAL;
493 // reset separating axis vector
494 dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};
495
496 // Epsilon value for checking axis vector length
497 const dReal fEpsilon = 1e-6f;
498
499 // Translate triangle to Cc cord.
500 SUBTRACT(v0 , vCapsulePosition, vV0);
501 SUBTRACT(v1 , vCapsulePosition, vV1);
502 SUBTRACT(v2 , vCapsulePosition, vV2);
503
504 // We begin to test for 19 separating axis now
505 // I wonder does it help if we employ the method like ISA-GJK???
506 // Or at least we should do experiment and find what axis will
507 // be most likely to be separating axis to check it first.
508
509 // Original
510 // axis vN
511 //vAxis = -vN;
512 vAxis[0] = - vN[0];
513 vAxis[1] = - vN[1];
514 vAxis[2] = - vN[2];
515 if (!_cldTestAxis( v0, v1, v2, vAxis, 1, TRUE))
516 {
517 return FALSE;
518 }
519
520 if (flags & dxTriMeshData::kEdge0)
521 {
522 // axis CxE0 - Edge 0
523 dCROSS(vAxis,=,vCapsuleAxis,vE0);
524 //vAxis = dCROSS( vCapsuleAxis cross vE0 );
525 if( _length2OfVector3( vAxis ) > fEpsilon ) {
526 if (!_cldTestAxis( v0, v1, v2, vAxis, 2)) {
527 return FALSE;
528 }
529 }
530 }
531
532 if (flags & dxTriMeshData::kEdge1)
533 {
534 // axis CxE1 - Edge 1
535 dCROSS(vAxis,=,vCapsuleAxis,vE1);
536 //vAxis = ( vCapsuleAxis cross vE1 );
537 if(_length2OfVector3( vAxis ) > fEpsilon ) {
538 if (!_cldTestAxis( v0, v1, v2, vAxis, 3)) {
539 return FALSE;
540 }
541 }
542 }
543
544 if (flags & dxTriMeshData::kEdge2)
545 {
546 // axis CxE2 - Edge 2
547 //vAxis = ( vCapsuleAxis cross vE2 );
548 dCROSS(vAxis,=,vCapsuleAxis,vE2);
549 if(_length2OfVector3( vAxis ) > fEpsilon ) {
550 if (!_cldTestAxis( v0, v1, v2, vAxis, 4)) {
551 return FALSE;
552 }
553 }
554 }
555
556 if (flags & dxTriMeshData::kEdge0)
557 {
558 // first capsule point
559 // axis ((Cp0-V0) x E0) x E0
560 _CalculateAxis(vCp0,v0,vE0,vE0,vAxis);
561 // vAxis = ( ( vCp0-v0) cross vE0 ) cross vE0;
562 if(_length2OfVector3( vAxis ) > fEpsilon ) {
563 if (!_cldTestAxis( v0, v1, v2, vAxis, 5)) {
564 return FALSE;
565 }
566 }
567 }
568
569 if (flags & dxTriMeshData::kEdge1)
570 {
571 // axis ((Cp0-V1) x E1) x E1
572 _CalculateAxis(vCp0,v1,vE1,vE1,vAxis);
573 //vAxis = ( ( vCp0-v1) cross vE1 ) cross vE1;
574 if(_length2OfVector3( vAxis ) > fEpsilon ) {
575 if (!_cldTestAxis( v0, v1, v2, vAxis, 6)) {
576 return FALSE;
577 }
578 }
579 }
580
581 if (flags & dxTriMeshData::kEdge2)
582 {
583 // axis ((Cp0-V2) x E2) x E2
584 _CalculateAxis(vCp0,v2,vE2,vE2,vAxis);
585 //vAxis = ( ( vCp0-v2) cross vE2 ) cross vE2;
586 if(_length2OfVector3( vAxis ) > fEpsilon ) {
587 if (!_cldTestAxis( v0, v1, v2, vAxis, 7)) {
588 return FALSE;
589 }
590 }
591 }
592
593 if (flags & dxTriMeshData::kEdge0)
594 {
595 // second capsule point
596 // axis ((Cp1-V0) x E0) x E0
597 _CalculateAxis(vCp1,v0,vE0,vE0,vAxis);
598 //vAxis = ( ( vCp1-v0 ) cross vE0 ) cross vE0;
599 if(_length2OfVector3( vAxis ) > fEpsilon ) {
600 if (!_cldTestAxis( v0, v1, v2, vAxis, 8)) {
601 return FALSE;
602 }
603 }
604 }
605
606 if (flags & dxTriMeshData::kEdge1)
607 {
608 // axis ((Cp1-V1) x E1) x E1
609 _CalculateAxis(vCp1,v1,vE1,vE1,vAxis);
610 //vAxis = ( ( vCp1-v1 ) cross vE1 ) cross vE1;
611 if(_length2OfVector3( vAxis ) > fEpsilon ) {
612 if (!_cldTestAxis( v0, v1, v2, vAxis, 9)) {
613 return FALSE;
614 }
615 }
616 }
617
618 if (flags & dxTriMeshData::kEdge2)
619 {
620 // axis ((Cp1-V2) x E2) x E2
621 _CalculateAxis(vCp1,v2,vE2,vE2,vAxis);
622 //vAxis = ( ( vCp1-v2 ) cross vE2 ) cross vE2;
623 if(_length2OfVector3( vAxis ) > fEpsilon ) {
624 if (!_cldTestAxis( v0, v1, v2, vAxis, 10)) {
625 return FALSE;
626 }
627 }
628 }
629
630 if (flags & dxTriMeshData::kVert0)
631 {
632 // first vertex on triangle
633 // axis ((V0-Cp0) x C) x C
634 _CalculateAxis(v0,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);
635 //vAxis = ( ( v0-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
636 if(_length2OfVector3( vAxis ) > fEpsilon ) {
637 if (!_cldTestAxis( v0, v1, v2, vAxis, 11)) {
638 return FALSE;
639 }
640 }
641 }
642
643 if (flags & dxTriMeshData::kVert1)
644 {
645 // second vertex on triangle
646 // axis ((V1-Cp0) x C) x C
647 _CalculateAxis(v1,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);
648 //vAxis = ( ( v1-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
649 if(_length2OfVector3( vAxis ) > fEpsilon ) {
650 if (!_cldTestAxis( v0, v1, v2, vAxis, 12)) {
651 return FALSE;
652 }
653 }
654 }
655
656 if (flags & dxTriMeshData::kVert2)
657 {
658 // third vertex on triangle
659 // axis ((V2-Cp0) x C) x C
660 _CalculateAxis(v2,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);
661 //vAxis = ( ( v2-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
662 if(_length2OfVector3( vAxis ) > fEpsilon ) {
663 if (!_cldTestAxis( v0, v1, v2, vAxis, 13)) {
664 return FALSE;
665 }
666 }
667 }
668
669 // Test as separating axes direction vectors between each triangle
670 // edge and each capsule's cap center
671
672 if (flags & dxTriMeshData::kVert0)
673 {
674 // first triangle vertex and first capsule point
675 //vAxis = v0 - vCp0;
676 SUBTRACT(v0,vCp0,vAxis);
677 if(_length2OfVector3( vAxis ) > fEpsilon ) {
678 if (!_cldTestAxis( v0, v1, v2, vAxis, 14)) {
679 return FALSE;
680 }
681 }
682 }
683
684 if (flags & dxTriMeshData::kVert1)
685 {
686 // second triangle vertex and first capsule point
687 //vAxis = v1 - vCp0;
688 SUBTRACT(v1,vCp0,vAxis);
689 if(_length2OfVector3( vAxis ) > fEpsilon ) {
690 if (!_cldTestAxis( v0, v1, v2, vAxis, 15)) {
691 return FALSE;
692 }
693 }
694 }
695
696 if (flags & dxTriMeshData::kVert2)
697 {
698 // third triangle vertex and first capsule point
699 //vAxis = v2 - vCp0;
700 SUBTRACT(v2,vCp0,vAxis);
701 if(_length2OfVector3( vAxis ) > fEpsilon ) {
702 if (!_cldTestAxis( v0, v1, v2, vAxis, 16)) {
703 return FALSE;
704 }
705 }
706 }
707
708 if (flags & dxTriMeshData::kVert0)
709 {
710 // first triangle vertex and second capsule point
711 //vAxis = v0 - vCp1;
712 SUBTRACT(v0,vCp1,vAxis);
713 if(_length2OfVector3( vAxis ) > fEpsilon ) {
714 if (!_cldTestAxis( v0, v1, v2, vAxis, 17)) {
715 return FALSE;
716 }
717 }
718 }
719
720 if (flags & dxTriMeshData::kVert1)
721 {
722 // second triangle vertex and second capsule point
723 //vAxis = v1 - vCp1;
724 SUBTRACT(v1,vCp1,vAxis);
725 if(_length2OfVector3( vAxis ) > fEpsilon ) {
726 if (!_cldTestAxis( v0, v1, v2, vAxis, 18)) {
727 return FALSE;
728 }
729 }
730 }
731
732 if (flags & dxTriMeshData::kVert2)
733 {
734 // third triangle vertex and second capsule point
735 //vAxis = v2 - vCp1;
736 SUBTRACT(v2,vCp1,vAxis);
737 if(_length2OfVector3( vAxis ) > fEpsilon ) {
738 if (!_cldTestAxis( v0, v1, v2, vAxis, 19)) {
739 return FALSE;
740 }
741 }
742 }
743
744 return TRUE;
745}
746
747// test one mesh triangle on intersection with capsule
748static void _cldTestOneTriangleVSCapsule( const dVector3 &v0,
749 const dVector3 &v1,
750 const dVector3 &v2,
751 uint8 flags)
752{
753
754 // calculate edges
755 SUBTRACT(v1,v0,vE0);
756 SUBTRACT(v2,v1,vE1);
757 SUBTRACT(v0,v2,vE2);
758
759 dVector3 _minus_vE0;
760 SUBTRACT(v0,v1,_minus_vE0);
761
762 // calculate poly normal
763 dCROSS(vN,=,vE1,_minus_vE0);
764 dNormalize3(vN);
765
766 // create plane from triangle
767 dReal plDistance = -dDOT(v0,vN);
768 dVector4 plTrianglePlane;
769 CONSTRUCTPLANE(plTrianglePlane,vN,plDistance);
770
771 // calculate capsule distance to plane
772 dReal fDistanceCapsuleCenterToPlane = POINTDISTANCE(plTrianglePlane,vCapsulePosition);
773
774 // Capsule must be over positive side of triangle
775 if(fDistanceCapsuleCenterToPlane < 0 /* && !bDoubleSided*/)
776 {
777 // if not don't generate contacts
778 return;
779 }
780
781 dVector3 vPnt0;
782 SET (vPnt0,v0);
783 dVector3 vPnt1;
784 SET (vPnt1,v1);
785 dVector3 vPnt2;
786 SET (vPnt2,v2);
787
788 if (fDistanceCapsuleCenterToPlane < 0 )
789 {
790 SET (vPnt0,v0);
791 SET (vPnt1,v2);
792 SET (vPnt2,v1);
793 }
794
795 // do intersection test and find best separating axis
796 if(!_cldTestSeparatingAxesOfCapsule(vPnt0, vPnt1, vPnt2, flags) )
797 {
798 // if not found do nothing
799 return;
800 }
801
802 // if best separation axis is not found
803 if ( iBestAxis == 0 )
804 {
805 // this should not happen (we should already exit in that case)
806 dIASSERT(FALSE);
807 // do nothing
808 return;
809 }
810
811 // calculate caps centers in absolute space
812 dVector3 vCposTrans;
813 vCposTrans[0] = vCapsulePosition[0] + vNormal[0]*vCapsuleRadius;
814 vCposTrans[1] = vCapsulePosition[1] + vNormal[1]*vCapsuleRadius;
815 vCposTrans[2] = vCapsulePosition[2] + vNormal[2]*vCapsuleRadius;
816
817 dVector3 vCEdgePoint0;
818 vCEdgePoint0[0] = vCposTrans[0] + vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
819 vCEdgePoint0[1] = vCposTrans[1] + vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
820 vCEdgePoint0[2] = vCposTrans[2] + vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
821
822 dVector3 vCEdgePoint1;
823 vCEdgePoint1[0] = vCposTrans[0] - vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
824 vCEdgePoint1[1] = vCposTrans[1] - vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
825 vCEdgePoint1[2] = vCposTrans[2] - vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
826
827 // transform capsule edge points into triangle space
828 vCEdgePoint0[0] -= vPnt0[0];
829 vCEdgePoint0[1] -= vPnt0[1];
830 vCEdgePoint0[2] -= vPnt0[2];
831
832 vCEdgePoint1[0] -= vPnt0[0];
833 vCEdgePoint1[1] -= vPnt0[1];
834 vCEdgePoint1[2] -= vPnt0[2];
835
836 dVector4 plPlane;
837 dVector3 _minus_vN;
838 _minus_vN[0] = -vN[0];
839 _minus_vN[1] = -vN[1];
840 _minus_vN[2] = -vN[2];
841 // triangle plane
842 CONSTRUCTPLANE(plPlane,_minus_vN,0);
843 //plPlane = Plane4f( -vN, 0);
844
845 if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
846 {
847 return;
848 }
849
850 // plane with edge 0
851 dVector3 vTemp;
852 dCROSS(vTemp,=,vN,vE0);
853 CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
854 if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
855 {
856 return;
857 }
858
859 dCROSS(vTemp,=,vN,vE1);
860 CONSTRUCTPLANE(plPlane, vTemp, -(dDOT(vE0,vTemp)-REAL(1e-5)));
861 if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
862 {
863 return;
864 }
865
866 dCROSS(vTemp,=,vN,vE2);
867 CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
868 if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) {
869 return;
870 }
871
872 // return capsule edge points into absolute space
873 vCEdgePoint0[0] += vPnt0[0];
874 vCEdgePoint0[1] += vPnt0[1];
875 vCEdgePoint0[2] += vPnt0[2];
876
877 vCEdgePoint1[0] += vPnt0[0];
878 vCEdgePoint1[1] += vPnt0[1];
879 vCEdgePoint1[2] += vPnt0[2];
880
881 // calculate depths for both contact points
882 SUBTRACT(vCEdgePoint0,vCapsulePosition,vTemp);
883 dReal fDepth0 = dDOT(vTemp,vNormal) - (fBestCenter-fBestrt);
884 SUBTRACT(vCEdgePoint1,vCapsulePosition,vTemp);
885 dReal fDepth1 = dDOT(vTemp,vNormal) - (fBestCenter-fBestrt);
886
887 // clamp depths to zero
888 if(fDepth0 < 0)
889 {
890 fDepth0 = 0.0f;
891 }
892
893 if(fDepth1 < 0 )
894 {
895 fDepth1 = 0.0f;
896 }
897
898 // Cached contacts's data
899 // contact 0
900 dIASSERT(ctContacts < (iFlags & NUMC_MASK)); // Do not call function if there is no room to store result
901 gLocalContacts[ctContacts].fDepth = fDepth0;
902 SET(gLocalContacts[ctContacts].vNormal,vNormal);
903 SET(gLocalContacts[ctContacts].vPos,vCEdgePoint0);
904 gLocalContacts[ctContacts].nFlags = 1;
905 ctContacts++;
906
907 if (ctContacts < (iFlags & NUMC_MASK)) {
908 // contact 1
909 gLocalContacts[ctContacts].fDepth = fDepth1;
910 SET(gLocalContacts[ctContacts].vNormal,vNormal);
911 SET(gLocalContacts[ctContacts].vPos,vCEdgePoint1);
912 gLocalContacts[ctContacts].nFlags = 1;
913 ctContacts++;
914 }
915
916}
917
918// capsule - trimesh by CroTeam
919// Ported by Nguyem Binh
920int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
921{
922 dIASSERT (skip >= (int)sizeof(dContactGeom));
923 dIASSERT (o1->type == dTriMeshClass);
924 dIASSERT (o2->type == dCapsuleClass);
925 dIASSERT ((flags & NUMC_MASK) >= 1);
926
927 dxTriMesh* TriMesh = (dxTriMesh*)o1;
928 gCylinder = o2;
929 gTriMesh = o1;
930
931 const dMatrix3* pRot = (const dMatrix3*) dGeomGetRotation(gCylinder);
932 memcpy(mCapsuleRotation,pRot,sizeof(dMatrix3));
933
934 const dVector3* pDst = (const dVector3*)dGeomGetPosition(gCylinder);
935 memcpy(vCapsulePosition,pDst,sizeof(dVector3));
936
937 vCapsuleAxis[0] = mCapsuleRotation[0*4 + nCAPSULE_AXIS];
938 vCapsuleAxis[1] = mCapsuleRotation[1*4 + nCAPSULE_AXIS];
939 vCapsuleAxis[2] = mCapsuleRotation[2*4 + nCAPSULE_AXIS];
940
941 // Get size of Capsule
942 dGeomCapsuleGetParams(gCylinder,&vCapsuleRadius,&fCapsuleSize);
943 fCapsuleSize += 2*vCapsuleRadius;
944
945 const dMatrix3* pTriRot = (const dMatrix3*)dGeomGetRotation(TriMesh);
946 memcpy(mTriMeshRot,pTriRot,sizeof(dMatrix3));
947
948 const dVector3* pTriPos = (const dVector3*)dGeomGetPosition(TriMesh);
949 memcpy(mTriMeshPos,pTriPos,sizeof(dVector3));
950
951 // global info for contact creation
952 iStride =skip;
953 iFlags =flags;
954 ContactGeoms =contact;
955
956 // reset contact counter
957 ctContacts = 0;
958
959 // reset best depth
960 fBestDepth = - MAX_REAL;
961 fBestCenter = 0;
962 fBestrt = 0;
963
964
965
966
967 // reset collision normal
968 vNormal[0] = REAL(0.0);
969 vNormal[1] = REAL(0.0);
970 vNormal[2] = REAL(0.0);
971
972 // Will it better to use LSS here? -> confirm Pierre.
973 OBBCollider& Collider = TriMesh->_OBBCollider;
974
975 // It is a potential issue to explicitly cast to float
976 // if custom width floating point type is introduced in OPCODE.
977 // It is necessary to make a typedef and cast to it
978 // (e.g. typedef float opc_float;)
979 // However I'm not sure in what header it should be added.
980
981 Point cCenter(/*(float)*/ vCapsulePosition[0], /*(float)*/ vCapsulePosition[1], /*(float)*/ vCapsulePosition[2]);
982 Point cExtents(/*(float)*/ vCapsuleRadius, /*(float)*/ vCapsuleRadius,/*(float)*/ fCapsuleSize/2);
983
984 Matrix3x3 obbRot;
985
986 obbRot[0][0] = /*(float)*/ mCapsuleRotation[0];
987 obbRot[1][0] = /*(float)*/ mCapsuleRotation[1];
988 obbRot[2][0] = /*(float)*/ mCapsuleRotation[2];
989
990 obbRot[0][1] = /*(float)*/ mCapsuleRotation[4];
991 obbRot[1][1] = /*(float)*/ mCapsuleRotation[5];
992 obbRot[2][1] = /*(float)*/ mCapsuleRotation[6];
993
994 obbRot[0][2] = /*(float)*/ mCapsuleRotation[8];
995 obbRot[1][2] = /*(float)*/ mCapsuleRotation[9];
996 obbRot[2][2] = /*(float)*/ mCapsuleRotation[10];
997
998 OBB obbCapsule(cCenter,cExtents,obbRot);
999
1000 Matrix4x4 CapsuleMatrix;
1001 MakeMatrix(vCapsulePosition, mCapsuleRotation, CapsuleMatrix);
1002
1003 Matrix4x4 MeshMatrix;
1004 MakeMatrix(mTriMeshPos, mTriMeshRot, MeshMatrix);
1005
1006 // TC results
1007 if (TriMesh->doBoxTC) {
1008 dxTriMesh::BoxTC* BoxTC = 0;
1009 for (int i = 0; i < TriMesh->BoxTCCache.size(); i++){
1010 if (TriMesh->BoxTCCache[i].Geom == gCylinder){
1011 BoxTC = &TriMesh->BoxTCCache[i];
1012 break;
1013 }
1014 }
1015 if (!BoxTC){
1016 TriMesh->BoxTCCache.push(dxTriMesh::BoxTC());
1017
1018 BoxTC = &TriMesh->BoxTCCache[TriMesh->BoxTCCache.size() - 1];
1019 BoxTC->Geom = gCylinder;
1020 BoxTC->FatCoeff = 1.0f;
1021 }
1022
1023 // Intersect
1024 Collider.SetTemporalCoherence(true);
1025 Collider.Collide(*BoxTC, obbCapsule, TriMesh->Data->BVTree, null, &MeshMatrix);
1026 }
1027 else {
1028 Collider.SetTemporalCoherence(false);
1029 Collider.Collide(dxTriMesh::defaultBoxCache, obbCapsule, TriMesh->Data->BVTree, null,&MeshMatrix);
1030 }
1031
1032 if (! Collider.GetContactStatus()) {
1033 // no collision occurred
1034 return 0;
1035 }
1036
1037 // Retrieve data
1038 int TriCount = Collider.GetNbTouchedPrimitives();
1039 const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
1040
1041 if (TriCount != 0)
1042 {
1043 if (TriMesh->ArrayCallback != null)
1044 {
1045 TriMesh->ArrayCallback(TriMesh, gCylinder, Triangles, TriCount);
1046 }
1047
1048 // allocate buffer for local contacts on stack
1049 gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(iFlags & NUMC_MASK));
1050
1051 unsigned int ctContacts0 = ctContacts;
1052
1053 uint8* UseFlags = TriMesh->Data->UseFlags;
1054
1055 // loop through all intersecting triangles
1056 for (int i = 0; i < TriCount; i++)
1057 {
1058 const int Triint = Triangles[i];
1059 if (!Callback(TriMesh, gCylinder, Triint)) continue;
1060
1061
1062 dVector3 dv[3];
1063 FetchTriangle(TriMesh, Triint, mTriMeshPos, mTriMeshRot, dv);
1064
1065 uint8 flags = UseFlags ? UseFlags[Triint] : dxTriMeshData::kUseAll;
1066
1067 // test this triangle
1068 _cldTestOneTriangleVSCapsule(dv[0],dv[1],dv[2], flags);
1069
1070 // fill-in tri index for generated contacts
1071 for (; ctContacts0<ctContacts; ctContacts0++)
1072 gLocalContacts[ctContacts0].triIndex = Triint;
1073
1074 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
1075 if(ctContacts>=(iFlags & NUMC_MASK))
1076 {
1077 break;
1078 }
1079
1080 }
1081 }
1082
1083 return _ProcessLocalContacts();
1084}
1085#endif
1086
1087// GIMPACT version
1088#if dTRIMESH_GIMPACT
1089#define nCAPSULE_AXIS 2
1090// capsule - trimesh By francisco leon
1091int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
1092{
1093 dIASSERT (skip >= (int)sizeof(dContactGeom));
1094 dIASSERT (o1->type == dTriMeshClass);
1095 dIASSERT (o2->type == dCapsuleClass);
1096 dIASSERT ((flags & NUMC_MASK) >= 1);
1097
1098 dxTriMesh* TriMesh = (dxTriMesh*)o1;
1099 dxGeom* gCylinder = o2;
1100
1101 //Get capsule params
1102 dMatrix3 mCapsuleRotation;
1103 dVector3 vCapsulePosition;
1104 dVector3 vCapsuleAxis;
1105 dReal vCapsuleRadius;
1106 dReal fCapsuleSize;
1107 dMatrix3* pRot = (dMatrix3*) dGeomGetRotation(gCylinder);
1108 memcpy(mCapsuleRotation,pRot,sizeof(dMatrix3));
1109 dVector3* pDst = (dVector3*)dGeomGetPosition(gCylinder);
1110 memcpy(vCapsulePosition,pDst,sizeof(dVector3));
1111 //Axis
1112 vCapsuleAxis[0] = mCapsuleRotation[0*4 + nCAPSULE_AXIS];
1113 vCapsuleAxis[1] = mCapsuleRotation[1*4 + nCAPSULE_AXIS];
1114 vCapsuleAxis[2] = mCapsuleRotation[2*4 + nCAPSULE_AXIS];
1115 // Get size of CCylinder
1116 dGeomCCylinderGetParams(gCylinder,&vCapsuleRadius,&fCapsuleSize);
1117 fCapsuleSize*=0.5f;
1118 //Set Capsule params
1119 GIM_CAPSULE_DATA capsule;
1120
1121 capsule.m_radius = vCapsuleRadius;
1122 VEC_SCALE(capsule.m_point1,fCapsuleSize,vCapsuleAxis);
1123 VEC_SUM(capsule.m_point1,vCapsulePosition,capsule.m_point1);
1124 VEC_SCALE(capsule.m_point2,-fCapsuleSize,vCapsuleAxis);
1125 VEC_SUM(capsule.m_point2,vCapsulePosition,capsule.m_point2);
1126
1127
1128//Create contact list
1129 GDYNAMIC_ARRAY trimeshcontacts;
1130 GIM_CREATE_CONTACT_LIST(trimeshcontacts);
1131
1132 //Collide trimeshe vs capsule
1133 gim_trimesh_capsule_collision(&TriMesh->m_collision_trimesh,&capsule,&trimeshcontacts);
1134
1135
1136 if(trimeshcontacts.m_size == 0)
1137 {
1138 GIM_DYNARRAY_DESTROY(trimeshcontacts);
1139 return 0;
1140 }
1141
1142 GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
1143
1144 unsigned contactcount = trimeshcontacts.m_size;
1145 unsigned contactmax = (unsigned)(flags & NUMC_MASK);
1146 if (contactcount > contactmax)
1147 {
1148 contactcount = contactmax;
1149 }
1150
1151 dContactGeom* pcontact;
1152 unsigned i;
1153
1154 for (i=0;i<contactcount;i++)
1155 {
1156 pcontact = SAFECONTACT(flags, contact, i, skip);
1157
1158 pcontact->pos[0] = ptrimeshcontacts->m_point[0];
1159 pcontact->pos[1] = ptrimeshcontacts->m_point[1];
1160 pcontact->pos[2] = ptrimeshcontacts->m_point[2];
1161 pcontact->pos[3] = 1.0f;
1162
1163 pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
1164 pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
1165 pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
1166 pcontact->normal[3] = 0;
1167
1168 pcontact->depth = ptrimeshcontacts->m_depth;
1169 pcontact->g1 = TriMesh;
1170 pcontact->g2 = gCylinder;
1171
1172 ptrimeshcontacts++;
1173 }
1174
1175 GIM_DYNARRAY_DESTROY(trimeshcontacts);
1176
1177 return (int)contactcount;
1178}
1179#endif
1180
1181#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_distance.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_distance.cpp
deleted file mode 100644
index 717c763..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_distance.cpp
+++ /dev/null
@@ -1,1255 +0,0 @@
1// This file contains some code based on the code from Magic Software.
2// That code is available under a Free Source License Agreement
3// that can be found at http://www.magic-software.com/License/free.pdf
4
5#include <ode/common.h>
6#include <ode/odemath.h>
7#include <ode/collision.h>
8#define TRIMESH_INTERNAL
9#include "collision_trimesh_internal.h"
10
11//------------------------------------------------------------------------------
12/**
13 @brief Finds the shortest distance squared between a point and a triangle.
14
15 @param pfSParam Barycentric coordinate of triangle at point closest to p (u)
16 @param pfTParam Barycentric coordinate of triangle at point closest to p (v)
17 @return Shortest distance squared.
18
19 The third Barycentric coordinate is implicit, ie. w = 1.0 - u - v
20
21 Taken from:
22 Magic Software, Inc.
23 http://www.magic-software.com
24*/
25dReal SqrDistancePointTri( const dVector3 p, const dVector3 triOrigin,
26 const dVector3 triEdge0, const dVector3 triEdge1,
27 dReal* pfSParam, dReal* pfTParam )
28{
29 dVector3 kDiff;
30 Vector3Subtract( triOrigin, p, kDiff );
31 dReal fA00 = dDOT( triEdge0, triEdge0 );
32 dReal fA01 = dDOT( triEdge0, triEdge1 );
33 dReal fA11 = dDOT( triEdge1, triEdge1 );
34 dReal fB0 = dDOT( kDiff, triEdge0 );
35 dReal fB1 = dDOT( kDiff, triEdge1 );
36 dReal fC = dDOT( kDiff, kDiff );
37 dReal fDet = dReal(fabs(fA00*fA11-fA01*fA01));
38 dReal fS = fA01*fB1-fA11*fB0;
39 dReal fT = fA01*fB0-fA00*fB1;
40 dReal fSqrDist;
41
42 if ( fS + fT <= fDet )
43 {
44 if ( fS < REAL(0.0) )
45 {
46 if ( fT < REAL(0.0) ) // region 4
47 {
48 if ( fB0 < REAL(0.0) )
49 {
50 fT = REAL(0.0);
51 if ( -fB0 >= fA00 )
52 {
53 fS = REAL(1.0);
54 fSqrDist = fA00+REAL(2.0)*fB0+fC;
55 }
56 else
57 {
58 fS = -fB0/fA00;
59 fSqrDist = fB0*fS+fC;
60 }
61 }
62 else
63 {
64 fS = REAL(0.0);
65 if ( fB1 >= REAL(0.0) )
66 {
67 fT = REAL(0.0);
68 fSqrDist = fC;
69 }
70 else if ( -fB1 >= fA11 )
71 {
72 fT = REAL(1.0);
73 fSqrDist = fA11+REAL(2.0)*fB1+fC;
74 }
75 else
76 {
77 fT = -fB1/fA11;
78 fSqrDist = fB1*fT+fC;
79 }
80 }
81 }
82 else // region 3
83 {
84 fS = REAL(0.0);
85 if ( fB1 >= REAL(0.0) )
86 {
87 fT = REAL(0.0);
88 fSqrDist = fC;
89 }
90 else if ( -fB1 >= fA11 )
91 {
92 fT = REAL(1.0);
93 fSqrDist = fA11+REAL(2.0)*fB1+fC;
94 }
95 else
96 {
97 fT = -fB1/fA11;
98 fSqrDist = fB1*fT+fC;
99 }
100 }
101 }
102 else if ( fT < REAL(0.0) ) // region 5
103 {
104 fT = REAL(0.0);
105 if ( fB0 >= REAL(0.0) )
106 {
107 fS = REAL(0.0);
108 fSqrDist = fC;
109 }
110 else if ( -fB0 >= fA00 )
111 {
112 fS = REAL(1.0);
113 fSqrDist = fA00+REAL(2.0)*fB0+fC;
114 }
115 else
116 {
117 fS = -fB0/fA00;
118 fSqrDist = fB0*fS+fC;
119 }
120 }
121 else // region 0
122 {
123 // minimum at interior point
124 if ( fDet == REAL(0.0) )
125 {
126 fS = REAL(0.0);
127 fT = REAL(0.0);
128 fSqrDist = dInfinity;
129 }
130 else
131 {
132 dReal fInvDet = REAL(1.0)/fDet;
133 fS *= fInvDet;
134 fT *= fInvDet;
135 fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
136 fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
137 }
138 }
139 }
140 else
141 {
142 dReal fTmp0, fTmp1, fNumer, fDenom;
143
144 if ( fS < REAL(0.0) ) // region 2
145 {
146 fTmp0 = fA01 + fB0;
147 fTmp1 = fA11 + fB1;
148 if ( fTmp1 > fTmp0 )
149 {
150 fNumer = fTmp1 - fTmp0;
151 fDenom = fA00-REAL(2.0)*fA01+fA11;
152 if ( fNumer >= fDenom )
153 {
154 fS = REAL(1.0);
155 fT = REAL(0.0);
156 fSqrDist = fA00+REAL(2.0)*fB0+fC;
157 }
158 else
159 {
160 fS = fNumer/fDenom;
161 fT = REAL(1.0) - fS;
162 fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
163 fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
164 }
165 }
166 else
167 {
168 fS = REAL(0.0);
169 if ( fTmp1 <= REAL(0.0) )
170 {
171 fT = REAL(1.0);
172 fSqrDist = fA11+REAL(2.0)*fB1+fC;
173 }
174 else if ( fB1 >= REAL(0.0) )
175 {
176 fT = REAL(0.0);
177 fSqrDist = fC;
178 }
179 else
180 {
181 fT = -fB1/fA11;
182 fSqrDist = fB1*fT+fC;
183 }
184 }
185 }
186 else if ( fT < REAL(0.0) ) // region 6
187 {
188 fTmp0 = fA01 + fB1;
189 fTmp1 = fA00 + fB0;
190 if ( fTmp1 > fTmp0 )
191 {
192 fNumer = fTmp1 - fTmp0;
193 fDenom = fA00-REAL(2.0)*fA01+fA11;
194 if ( fNumer >= fDenom )
195 {
196 fT = REAL(1.0);
197 fS = REAL(0.0);
198 fSqrDist = fA11+REAL(2.0)*fB1+fC;
199 }
200 else
201 {
202 fT = fNumer/fDenom;
203 fS = REAL(1.0) - fT;
204 fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
205 fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
206 }
207 }
208 else
209 {
210 fT = REAL(0.0);
211 if ( fTmp1 <= REAL(0.0) )
212 {
213 fS = REAL(1.0);
214 fSqrDist = fA00+REAL(2.0)*fB0+fC;
215 }
216 else if ( fB0 >= REAL(0.0) )
217 {
218 fS = REAL(0.0);
219 fSqrDist = fC;
220 }
221 else
222 {
223 fS = -fB0/fA00;
224 fSqrDist = fB0*fS+fC;
225 }
226 }
227 }
228 else // region 1
229 {
230 fNumer = fA11 + fB1 - fA01 - fB0;
231 if ( fNumer <= REAL(0.0) )
232 {
233 fS = REAL(0.0);
234 fT = REAL(1.0);
235 fSqrDist = fA11+REAL(2.0)*fB1+fC;
236 }
237 else
238 {
239 fDenom = fA00-REAL(2.0)*fA01+fA11;
240 if ( fNumer >= fDenom )
241 {
242 fS = REAL(1.0);
243 fT = REAL(0.0);
244 fSqrDist = fA00+REAL(2.0)*fB0+fC;
245 }
246 else
247 {
248 fS = fNumer/fDenom;
249 fT = REAL(1.0) - fS;
250 fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
251 fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
252 }
253 }
254 }
255 }
256
257 if ( pfSParam )
258 *pfSParam = (float)fS;
259
260 if ( pfTParam )
261 *pfTParam = (float)fT;
262
263 return dReal(fabs(fSqrDist));
264}
265
266//------------------------------------------------------------------------------
267/**
268 @brief Finds the shortest distance squared between two line segments.
269 @param pfSegP0 t value for seg1 where the shortest distance between
270 the segments exists.
271 @param pfSegP0 t value for seg2 where the shortest distance between
272 the segments exists.
273 @return Shortest distance squared.
274
275 Taken from:
276 Magic Software, Inc.
277 http://www.magic-software.com
278*/
279dReal SqrDistanceSegments( const dVector3 seg1Origin, const dVector3 seg1Direction,
280 const dVector3 seg2Origin, const dVector3 seg2Direction,
281 dReal* pfSegP0, dReal* pfSegP1 )
282{
283 const dReal gs_fTolerance = 1e-05f;
284 dVector3 kDiff, kNegDiff, seg1NegDirection;
285 Vector3Subtract( seg1Origin, seg2Origin, kDiff );
286 Vector3Negate( kDiff, kNegDiff );
287 dReal fA00 = dDOT( seg1Direction, seg1Direction );
288 Vector3Negate( seg1Direction, seg1NegDirection );
289 dReal fA01 = dDOT( seg1NegDirection, seg2Direction );
290 dReal fA11 = dDOT( seg2Direction, seg2Direction );
291 dReal fB0 = dDOT( kDiff, seg1Direction );
292 dReal fC = dDOT( kDiff, kDiff );
293 dReal fDet = dReal(fabs(fA00*fA11-fA01*fA01));
294 dReal fB1, fS, fT, fSqrDist, fTmp;
295
296 if ( fDet >= gs_fTolerance )
297 {
298 // line segments are not parallel
299 fB1 = dDOT( kNegDiff, seg2Direction );
300 fS = fA01*fB1-fA11*fB0;
301 fT = fA01*fB0-fA00*fB1;
302
303 if ( fS >= REAL(0.0) )
304 {
305 if ( fS <= fDet )
306 {
307 if ( fT >= REAL(0.0) )
308 {
309 if ( fT <= fDet ) // region 0 (interior)
310 {
311 // minimum at two interior points of 3D lines
312 dReal fInvDet = REAL(1.0)/fDet;
313 fS *= fInvDet;
314 fT *= fInvDet;
315 fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
316 fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
317 }
318 else // region 3 (side)
319 {
320 fT = REAL(1.0);
321 fTmp = fA01+fB0;
322 if ( fTmp >= REAL(0.0) )
323 {
324 fS = REAL(0.0);
325 fSqrDist = fA11+REAL(2.0)*fB1+fC;
326 }
327 else if ( -fTmp >= fA00 )
328 {
329 fS = REAL(1.0);
330 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB1+fTmp);
331 }
332 else
333 {
334 fS = -fTmp/fA00;
335 fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
336 }
337 }
338 }
339 else // region 7 (side)
340 {
341 fT = REAL(0.0);
342 if ( fB0 >= REAL(0.0) )
343 {
344 fS = REAL(0.0);
345 fSqrDist = fC;
346 }
347 else if ( -fB0 >= fA00 )
348 {
349 fS = REAL(1.0);
350 fSqrDist = fA00+REAL(2.0)*fB0+fC;
351 }
352 else
353 {
354 fS = -fB0/fA00;
355 fSqrDist = fB0*fS+fC;
356 }
357 }
358 }
359 else
360 {
361 if ( fT >= REAL(0.0) )
362 {
363 if ( fT <= fDet ) // region 1 (side)
364 {
365 fS = REAL(1.0);
366 fTmp = fA01+fB1;
367 if ( fTmp >= REAL(0.0) )
368 {
369 fT = REAL(0.0);
370 fSqrDist = fA00+REAL(2.0)*fB0+fC;
371 }
372 else if ( -fTmp >= fA11 )
373 {
374 fT = REAL(1.0);
375 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
376 }
377 else
378 {
379 fT = -fTmp/fA11;
380 fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
381 }
382 }
383 else // region 2 (corner)
384 {
385 fTmp = fA01+fB0;
386 if ( -fTmp <= fA00 )
387 {
388 fT = REAL(1.0);
389 if ( fTmp >= REAL(0.0) )
390 {
391 fS = REAL(0.0);
392 fSqrDist = fA11+REAL(2.0)*fB1+fC;
393 }
394 else
395 {
396 fS = -fTmp/fA00;
397 fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
398 }
399 }
400 else
401 {
402 fS = REAL(1.0);
403 fTmp = fA01+fB1;
404 if ( fTmp >= REAL(0.0) )
405 {
406 fT = REAL(0.0);
407 fSqrDist = fA00+REAL(2.0)*fB0+fC;
408 }
409 else if ( -fTmp >= fA11 )
410 {
411 fT = REAL(1.0);
412 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
413 }
414 else
415 {
416 fT = -fTmp/fA11;
417 fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
418 }
419 }
420 }
421 }
422 else // region 8 (corner)
423 {
424 if ( -fB0 < fA00 )
425 {
426 fT = REAL(0.0);
427 if ( fB0 >= REAL(0.0) )
428 {
429 fS = REAL(0.0);
430 fSqrDist = fC;
431 }
432 else
433 {
434 fS = -fB0/fA00;
435 fSqrDist = fB0*fS+fC;
436 }
437 }
438 else
439 {
440 fS = REAL(1.0);
441 fTmp = fA01+fB1;
442 if ( fTmp >= REAL(0.0) )
443 {
444 fT = REAL(0.0);
445 fSqrDist = fA00+REAL(2.0)*fB0+fC;
446 }
447 else if ( -fTmp >= fA11 )
448 {
449 fT = REAL(1.0);
450 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
451 }
452 else
453 {
454 fT = -fTmp/fA11;
455 fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
456 }
457 }
458 }
459 }
460 }
461 else
462 {
463 if ( fT >= REAL(0.0) )
464 {
465 if ( fT <= fDet ) // region 5 (side)
466 {
467 fS = REAL(0.0);
468 if ( fB1 >= REAL(0.0) )
469 {
470 fT = REAL(0.0);
471 fSqrDist = fC;
472 }
473 else if ( -fB1 >= fA11 )
474 {
475 fT = REAL(1.0);
476 fSqrDist = fA11+REAL(2.0)*fB1+fC;
477 }
478 else
479 {
480 fT = -fB1/fA11;
481 fSqrDist = fB1*fT+fC;
482 }
483 }
484 else // region 4 (corner)
485 {
486 fTmp = fA01+fB0;
487 if ( fTmp < REAL(0.0) )
488 {
489 fT = REAL(1.0);
490 if ( -fTmp >= fA00 )
491 {
492 fS = REAL(1.0);
493 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB1+fTmp);
494 }
495 else
496 {
497 fS = -fTmp/fA00;
498 fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
499 }
500 }
501 else
502 {
503 fS = REAL(0.0);
504 if ( fB1 >= REAL(0.0) )
505 {
506 fT = REAL(0.0);
507 fSqrDist = fC;
508 }
509 else if ( -fB1 >= fA11 )
510 {
511 fT = REAL(1.0);
512 fSqrDist = fA11+REAL(2.0)*fB1+fC;
513 }
514 else
515 {
516 fT = -fB1/fA11;
517 fSqrDist = fB1*fT+fC;
518 }
519 }
520 }
521 }
522 else // region 6 (corner)
523 {
524 if ( fB0 < REAL(0.0) )
525 {
526 fT = REAL(0.0);
527 if ( -fB0 >= fA00 )
528 {
529 fS = REAL(1.0);
530 fSqrDist = fA00+REAL(2.0)*fB0+fC;
531 }
532 else
533 {
534 fS = -fB0/fA00;
535 fSqrDist = fB0*fS+fC;
536 }
537 }
538 else
539 {
540 fS = REAL(0.0);
541 if ( fB1 >= REAL(0.0) )
542 {
543 fT = REAL(0.0);
544 fSqrDist = fC;
545 }
546 else if ( -fB1 >= fA11 )
547 {
548 fT = REAL(1.0);
549 fSqrDist = fA11+REAL(2.0)*fB1+fC;
550 }
551 else
552 {
553 fT = -fB1/fA11;
554 fSqrDist = fB1*fT+fC;
555 }
556 }
557 }
558 }
559 }
560 else
561 {
562 // line segments are parallel
563 if ( fA01 > REAL(0.0) )
564 {
565 // direction vectors form an obtuse angle
566 if ( fB0 >= REAL(0.0) )
567 {
568 fS = REAL(0.0);
569 fT = REAL(0.0);
570 fSqrDist = fC;
571 }
572 else if ( -fB0 <= fA00 )
573 {
574 fS = -fB0/fA00;
575 fT = REAL(0.0);
576 fSqrDist = fB0*fS+fC;
577 }
578 else
579 {
580 //fB1 = -kDiff % seg2.m;
581 fB1 = dDOT( kNegDiff, seg2Direction );
582 fS = REAL(1.0);
583 fTmp = fA00+fB0;
584 if ( -fTmp >= fA01 )
585 {
586 fT = REAL(1.0);
587 fSqrDist = fA00+fA11+fC+REAL(2.0)*(fA01+fB0+fB1);
588 }
589 else
590 {
591 fT = -fTmp/fA01;
592 fSqrDist = fA00+REAL(2.0)*fB0+fC+fT*(fA11*fT+REAL(2.0)*(fA01+fB1));
593 }
594 }
595 }
596 else
597 {
598 // direction vectors form an acute angle
599 if ( -fB0 >= fA00 )
600 {
601 fS = REAL(1.0);
602 fT = REAL(0.0);
603 fSqrDist = fA00+REAL(2.0)*fB0+fC;
604 }
605 else if ( fB0 <= REAL(0.0) )
606 {
607 fS = -fB0/fA00;
608 fT = REAL(0.0);
609 fSqrDist = fB0*fS+fC;
610 }
611 else
612 {
613 fB1 = dDOT( kNegDiff, seg2Direction );
614 fS = REAL(0.0);
615 if ( fB0 >= -fA01 )
616 {
617 fT = REAL(1.0);
618 fSqrDist = fA11+REAL(2.0)*fB1+fC;
619 }
620 else
621 {
622 fT = -fB0/fA01;
623 fSqrDist = fC+fT*(REAL(2.0)*fB1+fA11*fT);
624 }
625 }
626 }
627 }
628
629 if ( pfSegP0 )
630 *pfSegP0 = fS;
631
632 if ( pfSegP1 )
633 *pfSegP1 = fT;
634
635 return dReal(fabs(fSqrDist));
636}
637
638//------------------------------------------------------------------------------
639/**
640 @brief Finds the shortest distance squared between a line segment and
641 a triangle.
642
643 @param pfSegP t value for the line segment where the shortest distance between
644 the segment and the triangle occurs.
645 So the point along the segment that is the shortest distance
646 away from the triangle can be obtained by (seg.end - seg.start) * t.
647 @param pfTriP0 Barycentric coordinate of triangle at point closest to seg (u)
648 @param pfTriP1 Barycentric coordinate of triangle at point closest to seg (v)
649 @return Shortest distance squared.
650
651 The third Barycentric coordinate is implicit, ie. w = 1.0 - u - v
652
653 Taken from:
654 Magic Software, Inc.
655 http://www.magic-software.com
656*/
657dReal SqrDistanceSegTri( const dVector3 segOrigin, const dVector3 segEnd,
658 const dVector3 triOrigin,
659 const dVector3 triEdge0, const dVector3 triEdge1,
660 dReal* pfSegP, dReal* pfTriP0, dReal* pfTriP1 )
661{
662 const dReal gs_fTolerance = 1e-06f;
663 dVector3 segDirection, segNegDirection, kDiff, kNegDiff;
664 Vector3Subtract( segEnd, segOrigin, segDirection );
665 Vector3Negate( segDirection, segNegDirection );
666 Vector3Subtract( triOrigin, segOrigin, kDiff );
667 Vector3Negate( kDiff, kNegDiff );
668 dReal fA00 = dDOT( segDirection, segDirection );
669 dReal fA01 = dDOT( segNegDirection, triEdge0 );
670 dReal fA02 = dDOT( segNegDirection, triEdge1 );
671 dReal fA11 = dDOT( triEdge0, triEdge0 );
672 dReal fA12 = dDOT( triEdge0, triEdge1 );
673 dReal fA22 = dDOT( triEdge1, triEdge1 );
674 dReal fB0 = dDOT( kNegDiff, segDirection );
675 dReal fB1 = dDOT( kDiff, triEdge0 );
676 dReal fB2 = dDOT( kDiff, triEdge1 );
677
678 dVector3 kTriSegOrigin, kTriSegDirection, kPt;
679 dReal fSqrDist, fSqrDist0, fR, fS, fT, fR0, fS0, fT0;
680
681 // Set up for a relative error test on the angle between ray direction
682 // and triangle normal to determine parallel/nonparallel status.
683 dVector3 kN;
684 dCROSS( kN, =, triEdge0, triEdge1 );
685 dReal fNSqrLen = dDOT( kN, kN );
686 dReal fDot = dDOT( segDirection, kN );
687 bool bNotParallel = (fDot*fDot >= gs_fTolerance*fA00*fNSqrLen);
688
689 if ( bNotParallel )
690 {
691 dReal fCof00 = fA11*fA22-fA12*fA12;
692 dReal fCof01 = fA02*fA12-fA01*fA22;
693 dReal fCof02 = fA01*fA12-fA02*fA11;
694 dReal fCof11 = fA00*fA22-fA02*fA02;
695 dReal fCof12 = fA02*fA01-fA00*fA12;
696 dReal fCof22 = fA00*fA11-fA01*fA01;
697 dReal fInvDet = REAL(1.0)/(fA00*fCof00+fA01*fCof01+fA02*fCof02);
698 dReal fRhs0 = -fB0*fInvDet;
699 dReal fRhs1 = -fB1*fInvDet;
700 dReal fRhs2 = -fB2*fInvDet;
701
702 fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2;
703 fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2;
704 fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2;
705
706 if ( fR < REAL(0.0) )
707 {
708 if ( fS+fT <= REAL(1.0) )
709 {
710 if ( fS < REAL(0.0) )
711 {
712 if ( fT < REAL(0.0) ) // region 4m
713 {
714 // min on face s=0 or t=0 or r=0
715 Vector3Copy( triOrigin, kTriSegOrigin );
716 Vector3Copy( triEdge1, kTriSegDirection );
717 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
718 kTriSegOrigin, kTriSegDirection,
719 &fR, &fT );
720 fS = REAL(0.0);
721 Vector3Copy( triOrigin, kTriSegOrigin );
722 Vector3Copy( triEdge0, kTriSegDirection );
723 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
724 kTriSegOrigin, kTriSegDirection,
725 &fR0, &fS0 );
726 fT0 = REAL(0.0);
727 if ( fSqrDist0 < fSqrDist )
728 {
729 fSqrDist = fSqrDist0;
730 fR = fR0;
731 fS = fS0;
732 fT = fT0;
733 }
734 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
735 &fS0, &fT0 );
736 fR0 = REAL(0.0);
737 if ( fSqrDist0 < fSqrDist )
738 {
739 fSqrDist = fSqrDist0;
740 fR = fR0;
741 fS = fS0;
742 fT = fT0;
743 }
744 }
745 else // region 3m
746 {
747 // min on face s=0 or r=0
748 Vector3Copy( triOrigin, kTriSegOrigin );
749 Vector3Copy( triEdge1, kTriSegDirection );
750 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
751 kTriSegOrigin, kTriSegDirection,
752 &fR,&fT );
753 fS = REAL(0.0);
754 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
755 &fS0, &fT0 );
756 fR0 = REAL(0.0);
757 if ( fSqrDist0 < fSqrDist )
758 {
759 fSqrDist = fSqrDist0;
760 fR = fR0;
761 fS = fS0;
762 fT = fT0;
763 }
764 }
765 }
766 else if ( fT < REAL(0.0) ) // region 5m
767 {
768 // min on face t=0 or r=0
769 Vector3Copy( triOrigin, kTriSegOrigin );
770 Vector3Copy( triEdge0, kTriSegDirection );
771 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
772 kTriSegOrigin, kTriSegDirection,
773 &fR, &fS );
774 fT = REAL(0.0);
775 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
776 &fS0, &fT0 );
777 fR0 = REAL(0.0);
778 if ( fSqrDist0 < fSqrDist )
779 {
780 fSqrDist = fSqrDist0;
781 fR = fR0;
782 fS = fS0;
783 fT = fT0;
784 }
785 }
786 else // region 0m
787 {
788 // min on face r=0
789 fSqrDist = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
790 &fS, &fT );
791 fR = REAL(0.0);
792 }
793 }
794 else
795 {
796 if ( fS < REAL(0.0) ) // region 2m
797 {
798 // min on face s=0 or s+t=1 or r=0
799 Vector3Copy( triOrigin, kTriSegOrigin );
800 Vector3Copy( triEdge1, kTriSegDirection );
801 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
802 kTriSegOrigin, kTriSegDirection,
803 &fR, &fT );
804 fS = REAL(0.0);
805 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
806 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
807 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
808 kTriSegOrigin, kTriSegDirection,
809 &fR0, &fT0 );
810 fS0 = REAL(1.0) - fT0;
811 if ( fSqrDist0 < fSqrDist )
812 {
813 fSqrDist = fSqrDist0;
814 fR = fR0;
815 fS = fS0;
816 fT = fT0;
817 }
818 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
819 &fS0, &fT0 );
820 fR0 = REAL(0.0);
821 if ( fSqrDist0 < fSqrDist )
822 {
823 fSqrDist = fSqrDist0;
824 fR = fR0;
825 fS = fS0;
826 fT = fT0;
827 }
828 }
829 else if ( fT < REAL(0.0) ) // region 6m
830 {
831 // min on face t=0 or s+t=1 or r=0
832 Vector3Copy( triOrigin, kTriSegOrigin );
833 Vector3Copy( triEdge0, kTriSegDirection );
834 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
835 kTriSegOrigin, kTriSegDirection,
836 &fR, &fS );
837 fT = REAL(0.0);
838 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
839 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
840 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
841 kTriSegOrigin, kTriSegDirection,
842 &fR0, &fT0 );
843 fS0 = REAL(1.0) - fT0;
844 if ( fSqrDist0 < fSqrDist )
845 {
846 fSqrDist = fSqrDist0;
847 fR = fR0;
848 fS = fS0;
849 fT = fT0;
850 }
851 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
852 &fS0, &fT0 );
853 fR0 = REAL(0.0);
854 if ( fSqrDist0 < fSqrDist )
855 {
856 fSqrDist = fSqrDist0;
857 fR = fR0;
858 fS = fS0;
859 fT = fT0;
860 }
861 }
862 else // region 1m
863 {
864 // min on face s+t=1 or r=0
865 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
866 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
867 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
868 kTriSegOrigin, kTriSegDirection,
869 &fR, &fT );
870 fS = REAL(1.0) - fT;
871 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
872 &fS0, &fT0 );
873 fR0 = REAL(0.0);
874 if ( fSqrDist0 < fSqrDist )
875 {
876 fSqrDist = fSqrDist0;
877 fR = fR0;
878 fS = fS0;
879 fT = fT0;
880 }
881 }
882 }
883 }
884 else if ( fR <= REAL(1.0) )
885 {
886 if ( fS+fT <= REAL(1.0) )
887 {
888 if ( fS < REAL(0.0) )
889 {
890 if ( fT < REAL(0.0) ) // region 4
891 {
892 // min on face s=0 or t=0
893 Vector3Copy( triOrigin, kTriSegOrigin );
894 Vector3Copy( triEdge1, kTriSegDirection );
895 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
896 kTriSegOrigin, kTriSegDirection,
897 &fR, &fT );
898 fS = REAL(0.0);
899 Vector3Copy( triOrigin, kTriSegOrigin );
900 Vector3Copy( triEdge0, kTriSegDirection );
901 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
902 kTriSegOrigin, kTriSegDirection,
903 &fR0, &fS0 );
904 fT0 = REAL(0.0);
905 if ( fSqrDist0 < fSqrDist )
906 {
907 fSqrDist = fSqrDist0;
908 fR = fR0;
909 fS = fS0;
910 fT = fT0;
911 }
912 }
913 else // region 3
914 {
915 // min on face s=0
916 Vector3Copy( triOrigin, kTriSegOrigin );
917 Vector3Copy( triEdge1, kTriSegDirection );
918 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
919 kTriSegOrigin, kTriSegDirection,
920 &fR, &fT );
921 fS = REAL(0.0);
922 }
923 }
924 else if ( fT < REAL(0.0) ) // region 5
925 {
926 // min on face t=0
927 Vector3Copy( triOrigin, kTriSegOrigin );
928 Vector3Copy( triEdge0, kTriSegDirection );
929 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
930 kTriSegOrigin, kTriSegDirection,
931 &fR, &fS );
932 fT = REAL(0.0);
933 }
934 else // region 0
935 {
936 // global minimum is interior, done
937 fSqrDist = REAL(0.0);
938 }
939 }
940 else
941 {
942 if ( fS < REAL(0.0) ) // region 2
943 {
944 // min on face s=0 or s+t=1
945 Vector3Copy( triOrigin, kTriSegOrigin );
946 Vector3Copy( triEdge1, kTriSegDirection );
947 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
948 kTriSegOrigin, kTriSegDirection,
949 &fR, &fT );
950 fS = REAL(0.0);
951 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
952 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
953 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
954 kTriSegOrigin, kTriSegDirection,
955 &fR0, &fT0 );
956 fS0 = REAL(1.0) - fT0;
957 if ( fSqrDist0 < fSqrDist )
958 {
959 fSqrDist = fSqrDist0;
960 fR = fR0;
961 fS = fS0;
962 fT = fT0;
963 }
964 }
965 else if ( fT < REAL(0.0) ) // region 6
966 {
967 // min on face t=0 or s+t=1
968 Vector3Copy( triOrigin, kTriSegOrigin );
969 Vector3Copy( triEdge0, kTriSegDirection );
970 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
971 kTriSegOrigin, kTriSegDirection,
972 &fR, &fS );
973 fT = REAL(0.0);
974 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
975 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
976 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
977 kTriSegOrigin, kTriSegDirection,
978 &fR0, &fT0 );
979 fS0 = REAL(1.0) - fT0;
980 if ( fSqrDist0 < fSqrDist )
981 {
982 fSqrDist = fSqrDist0;
983 fR = fR0;
984 fS = fS0;
985 fT = fT0;
986 }
987 }
988 else // region 1
989 {
990 // min on face s+t=1
991 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
992 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
993 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
994 kTriSegOrigin, kTriSegDirection,
995 &fR, &fT );
996 fS = REAL(1.0) - fT;
997 }
998 }
999 }
1000 else // fR > 1
1001 {
1002 if ( fS+fT <= REAL(1.0) )
1003 {
1004 if ( fS < REAL(0.0) )
1005 {
1006 if ( fT < REAL(0.0) ) // region 4p
1007 {
1008 // min on face s=0 or t=0 or r=1
1009 Vector3Copy( triOrigin, kTriSegOrigin );
1010 Vector3Copy( triEdge1, kTriSegDirection );
1011 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1012 kTriSegOrigin, kTriSegDirection,
1013 &fR, &fT );
1014 fS = REAL(0.0);
1015 Vector3Copy( triOrigin, kTriSegOrigin );
1016 Vector3Copy( triEdge0, kTriSegDirection );
1017 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
1018 kTriSegOrigin, kTriSegDirection,
1019 &fR0, &fS0 );
1020 fT0 = REAL(0.0);
1021 if ( fSqrDist0 < fSqrDist )
1022 {
1023 fSqrDist = fSqrDist0;
1024 fR = fR0;
1025 fS = fS0;
1026 fT = fT0;
1027 }
1028 Vector3Add( segOrigin, segDirection, kPt );
1029 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1030 &fS0, &fT0 );
1031 fR0 = REAL(1.0);
1032 if ( fSqrDist0 < fSqrDist )
1033 {
1034 fSqrDist = fSqrDist0;
1035 fR = fR0;
1036 fS = fS0;
1037 fT = fT0;
1038 }
1039 }
1040 else // region 3p
1041 {
1042 // min on face s=0 or r=1
1043 Vector3Copy( triOrigin, kTriSegOrigin );
1044 Vector3Copy( triEdge1, kTriSegDirection );
1045 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1046 kTriSegOrigin, kTriSegDirection,
1047 &fR, &fT );
1048 fS = REAL(0.0);
1049 Vector3Add( segOrigin, segDirection, kPt );
1050 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1051 &fS0, &fT0 );
1052 fR0 = REAL(1.0);
1053 if ( fSqrDist0 < fSqrDist )
1054 {
1055 fSqrDist = fSqrDist0;
1056 fR = fR0;
1057 fS = fS0;
1058 fT = fT0;
1059 }
1060 }
1061 }
1062 else if ( fT < REAL(0.0) ) // region 5p
1063 {
1064 // min on face t=0 or r=1
1065 Vector3Copy( triOrigin, kTriSegOrigin );
1066 Vector3Copy( triEdge0, kTriSegDirection );
1067 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1068 kTriSegOrigin, kTriSegDirection,
1069 &fR, &fS );
1070 fT = REAL(0.0);
1071 Vector3Add( segOrigin, segDirection, kPt );
1072 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1073 &fS0, &fT0 );
1074 fR0 = REAL(1.0);
1075 if ( fSqrDist0 < fSqrDist )
1076 {
1077 fSqrDist = fSqrDist0;
1078 fR = fR0;
1079 fS = fS0;
1080 fT = fT0;
1081 }
1082 }
1083 else // region 0p
1084 {
1085 // min face on r=1
1086 Vector3Add( segOrigin, segDirection, kPt );
1087 fSqrDist = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1088 &fS, &fT );
1089 fR = REAL(1.0);
1090 }
1091 }
1092 else
1093 {
1094 if ( fS < REAL(0.0) ) // region 2p
1095 {
1096 // min on face s=0 or s+t=1 or r=1
1097 Vector3Copy( triOrigin, kTriSegOrigin );
1098 Vector3Copy( triEdge1, kTriSegDirection );
1099 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1100 kTriSegOrigin, kTriSegDirection,
1101 &fR, &fT );
1102 fS = REAL(0.0);
1103 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
1104 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
1105 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
1106 kTriSegOrigin, kTriSegDirection,
1107 &fR0, &fT0 );
1108 fS0 = REAL(1.0) - fT0;
1109 if ( fSqrDist0 < fSqrDist )
1110 {
1111 fSqrDist = fSqrDist0;
1112 fR = fR0;
1113 fS = fS0;
1114 fT = fT0;
1115 }
1116 Vector3Add( segOrigin, segDirection, kPt );
1117 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1118 &fS0, &fT0 );
1119 fR0 = REAL(1.0);
1120 if ( fSqrDist0 < fSqrDist )
1121 {
1122 fSqrDist = fSqrDist0;
1123 fR = fR0;
1124 fS = fS0;
1125 fT = fT0;
1126 }
1127 }
1128 else if ( fT < REAL(0.0) ) // region 6p
1129 {
1130 // min on face t=0 or s+t=1 or r=1
1131 Vector3Copy( triOrigin, kTriSegOrigin );
1132 Vector3Copy( triEdge0, kTriSegDirection );
1133 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1134 kTriSegOrigin, kTriSegDirection,
1135 &fR, &fS );
1136 fT = REAL(0.0);
1137 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
1138 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
1139 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
1140 kTriSegOrigin, kTriSegDirection,
1141 &fR0, &fT0 );
1142 fS0 = REAL(1.0) - fT0;
1143 if ( fSqrDist0 < fSqrDist )
1144 {
1145 fSqrDist = fSqrDist0;
1146 fR = fR0;
1147 fS = fS0;
1148 fT = fT0;
1149 }
1150 Vector3Add( segOrigin, segDirection, kPt );
1151 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1152 &fS0, &fT0 );
1153 fR0 = REAL(1.0);
1154 if ( fSqrDist0 < fSqrDist )
1155 {
1156 fSqrDist = fSqrDist0;
1157 fR = fR0;
1158 fS = fS0;
1159 fT = fT0;
1160 }
1161 }
1162 else // region 1p
1163 {
1164 // min on face s+t=1 or r=1
1165 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
1166 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
1167 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1168 kTriSegOrigin, kTriSegDirection,
1169 &fR, &fT );
1170 fS = REAL(1.0) - fT;
1171 Vector3Add( segOrigin, segDirection, kPt );
1172 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1173 &fS0, &fT0 );
1174 fR0 = REAL(1.0);
1175 if ( fSqrDist0 < fSqrDist )
1176 {
1177 fSqrDist = fSqrDist0;
1178 fR = fR0;
1179 fS = fS0;
1180 fT = fT0;
1181 }
1182 }
1183 }
1184 }
1185 }
1186 else
1187 {
1188 // segment and triangle are parallel
1189 Vector3Copy( triOrigin, kTriSegOrigin );
1190 Vector3Copy( triEdge0, kTriSegDirection );
1191 fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
1192 kTriSegOrigin, kTriSegDirection, &fR, &fS );
1193 fT = REAL(0.0);
1194
1195 Vector3Copy( triEdge1, kTriSegDirection );
1196 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
1197 kTriSegOrigin, kTriSegDirection,
1198 &fR0, &fT0 );
1199 fS0 = REAL(0.0);
1200 if ( fSqrDist0 < fSqrDist )
1201 {
1202 fSqrDist = fSqrDist0;
1203 fR = fR0;
1204 fS = fS0;
1205 fT = fT0;
1206 }
1207
1208 Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
1209 Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
1210 fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
1211 kTriSegOrigin, kTriSegDirection, &fR0, &fT0 );
1212 fS0 = REAL(1.0) - fT0;
1213 if ( fSqrDist0 < fSqrDist )
1214 {
1215 fSqrDist = fSqrDist0;
1216 fR = fR0;
1217 fS = fS0;
1218 fT = fT0;
1219 }
1220
1221 fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
1222 &fS0, &fT0 );
1223 fR0 = REAL(0.0);
1224 if ( fSqrDist0 < fSqrDist )
1225 {
1226 fSqrDist = fSqrDist0;
1227 fR = fR0;
1228 fS = fS0;
1229 fT = fT0;
1230 }
1231
1232 Vector3Add( segOrigin, segDirection, kPt );
1233 fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
1234 &fS0, &fT0 );
1235 fR0 = REAL(1.0);
1236 if ( fSqrDist0 < fSqrDist )
1237 {
1238 fSqrDist = fSqrDist0;
1239 fR = fR0;
1240 fS = fS0;
1241 fT = fT0;
1242 }
1243 }
1244
1245 if ( pfSegP )
1246 *pfSegP = fR;
1247
1248 if ( pfTriP0 )
1249 *pfTriP0 = fS;
1250
1251 if ( pfTriP1 )
1252 *pfTriP1 = fT;
1253
1254 return fSqrDist;
1255}
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_gimpact.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_gimpact.cpp
deleted file mode 100644
index 229966b..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_gimpact.cpp
+++ /dev/null
@@ -1,456 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/collision.h>
24#include <ode/matrix.h>
25#include <ode/rotation.h>
26#include <ode/odemath.h>
27
28#if dTRIMESH_ENABLED
29
30#include "collision_util.h"
31#define TRIMESH_INTERNAL
32#include "collision_trimesh_internal.h"
33
34#if dTRIMESH_GIMPACT
35
36void dxTriMeshData::Preprocess(){ // stub
37}
38
39dTriMeshDataID dGeomTriMeshDataCreate(){
40 return new dxTriMeshData();
41}
42
43void dGeomTriMeshDataDestroy(dTriMeshDataID g){
44 delete g;
45}
46
47void dGeomTriMeshSetLastTransform( dxGeom* g, dMatrix4 last_trans ) { //stub
48}
49
50dReal* dGeomTriMeshGetLastTransform( dxGeom* g ) {
51 return NULL; // stub
52}
53
54void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data) { //stub
55}
56
57void* dGeomTriMeshDataGet(dTriMeshDataID g, int data_id) {
58 dUASSERT(g, "argument not trimesh data");
59 return NULL; // stub
60}
61
62void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
63 const void* Vertices, int VertexStride, int VertexCount,
64 const void* Indices, int IndexCount, int TriStride,
65 const void* Normals)
66{
67 dUASSERT(g, "argument not trimesh data");
68 dIASSERT(Vertices);
69 dIASSERT(Indices);
70
71 g->Build(Vertices, VertexStride, VertexCount,
72 Indices, IndexCount, TriStride,
73 Normals,
74 true);
75}
76
77
78void dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
79 const void* Vertices, int VertexStride, int VertexCount,
80 const void* Indices, int IndexCount, int TriStride)
81{
82 dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount,
83 Indices, IndexCount, TriStride, (void*)NULL);
84}
85
86
87void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g,
88 const void* Vertices, int VertexStride, int VertexCount,
89 const void* Indices, int IndexCount, int TriStride,
90 const void* Normals)
91{
92 dUASSERT(g, "argument not trimesh data");
93
94 g->Build(Vertices, VertexStride, VertexCount,
95 Indices, IndexCount, TriStride,
96 Normals,
97 false);
98}
99
100
101void dGeomTriMeshDataBuildDouble(dTriMeshDataID g,
102 const void* Vertices, int VertexStride, int VertexCount,
103 const void* Indices, int IndexCount, int TriStride) {
104 dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount,
105 Indices, IndexCount, TriStride, NULL);
106}
107
108
109void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
110 const dReal* Vertices, int VertexCount,
111 const int* Indices, int IndexCount,
112 const int* Normals){
113#ifdef dSINGLE
114 dGeomTriMeshDataBuildSingle1(g,
115 Vertices, 4 * sizeof(dReal), VertexCount,
116 Indices, IndexCount, 3 * sizeof(unsigned int),
117 Normals);
118#else
119 dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount,
120 Indices, IndexCount, 3 * sizeof(unsigned int),
121 Normals);
122#endif
123}
124
125
126void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
127 const dReal* Vertices, int VertexCount,
128 const int* Indices, int IndexCount) {
129 dGeomTriMeshDataBuildSimple1(g,
130 Vertices, VertexCount, Indices, IndexCount,
131 (const int*)NULL);
132}
133
134void dGeomTriMeshDataPreprocess(dTriMeshDataID g)
135{
136 dUASSERT(g, "argument not trimesh data");
137 g->Preprocess();
138}
139
140void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen)
141{
142 dUASSERT(g, "argument not trimesh data");
143 *buf = NULL;
144 *bufLen = 0;
145}
146
147void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf)
148{
149 dUASSERT(g, "argument not trimesh data");
150// g->UseFlags = buf;
151}
152
153
154// Trimesh
155
156dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1){
157 type = dTriMeshClass;
158
159 dGeomTriMeshSetData(this,Data);
160
161 /* TC has speed/space 'issues' that don't make it a clear
162 win by default on spheres/boxes. */
163 this->doSphereTC = true;
164 this->doBoxTC = true;
165 this->doCapsuleTC = true;
166
167}
168
169dxTriMesh::~dxTriMesh(){
170
171 //Terminate Trimesh
172 gim_trimesh_destroy(&m_collision_trimesh);
173}
174
175
176void dxTriMesh::ClearTCCache(){
177
178}
179
180
181int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
182 return 1;
183}
184
185
186void dxTriMesh::computeAABB()
187{
188 //update trimesh transform
189 mat4f transform;
190 IDENTIFY_MATRIX_4X4(transform);
191 MakeMatrix(this, transform);
192 gim_trimesh_set_tranform(&m_collision_trimesh,transform);
193
194 //Update trimesh boxes
195 gim_trimesh_update(&m_collision_trimesh);
196
197 memcpy(aabb,&m_collision_trimesh.m_aabbset.m_global_bound,6*sizeof(GREAL));
198}
199
200
201void dxTriMeshData::UpdateData()
202{
203// BVTree.Refit();
204}
205
206
207dGeomID dCreateTriMesh(dSpaceID space,
208 dTriMeshDataID Data,
209 dTriCallback* Callback,
210 dTriArrayCallback* ArrayCallback,
211 dTriRayCallback* RayCallback)
212{
213 dxTriMesh* Geom = new dxTriMesh(space, Data);
214 Geom->Callback = Callback;
215 Geom->ArrayCallback = ArrayCallback;
216 Geom->RayCallback = RayCallback;
217
218 return Geom;
219}
220
221void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback)
222{
223 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
224 ((dxTriMesh*)g)->Callback = Callback;
225}
226
227dTriCallback* dGeomTriMeshGetCallback(dGeomID g)
228{
229 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
230 return ((dxTriMesh*)g)->Callback;
231}
232
233void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback)
234{
235 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
236 ((dxTriMesh*)g)->ArrayCallback = ArrayCallback;
237}
238
239dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g)
240{
241 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
242 return ((dxTriMesh*)g)->ArrayCallback;
243}
244
245void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback)
246{
247 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
248 ((dxTriMesh*)g)->RayCallback = Callback;
249}
250
251dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g)
252{
253 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
254 return ((dxTriMesh*)g)->RayCallback;
255}
256
257void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data)
258{
259 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
260 dxTriMesh* mesh = (dxTriMesh*) g;
261 mesh->Data = Data;
262 // I changed my data -- I know nothing about my own AABB anymore.
263 ((dxTriMesh*)g)->gflags |= (GEOM_DIRTY|GEOM_AABB_BAD);
264
265 // GIMPACT only supports stride 12, so we need to catch the error early.
266 dUASSERT
267 (
268 Data->m_VertexStride == 3*sizeof(dReal) && Data->m_TriStride == 3*sizeof(int),
269 "Gimpact trimesh only supports a stride of 3 dReal/int\n"
270 "This means that you cannot use dGeomTriMeshDataBuildSimple() with Gimpact.\n"
271 "Change the stride, or use Opcode trimeshes instead.\n"
272 );
273
274 //Create trimesh
275 if ( Data->m_Vertices )
276 gim_trimesh_create_from_data
277 (
278 &mesh->m_collision_trimesh, // gimpact mesh
279 ( vec3f *)(&Data->m_Vertices[0]), // vertices
280 Data->m_VertexCount, // nr of verts
281 0, // copy verts?
282 ( GUINT *)(&Data->m_Indices[0]), // indices
283 Data->m_TriangleCount*3, // nr of indices
284 0, // copy indices?
285 1 // transformed reply
286 );
287}
288
289dTriMeshDataID dGeomTriMeshGetData(dGeomID g)
290{
291 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
292 return ((dxTriMesh*)g)->Data;
293}
294
295
296
297void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable)
298{
299 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
300
301 switch (geomClass)
302 {
303 case dSphereClass:
304 ((dxTriMesh*)g)->doSphereTC = (1 == enable);
305 break;
306 case dBoxClass:
307 ((dxTriMesh*)g)->doBoxTC = (1 == enable);
308 break;
309 case dCapsuleClass:
310// case dCCylinderClass:
311 ((dxTriMesh*)g)->doCapsuleTC = (1 == enable);
312 break;
313 }
314}
315
316int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass)
317{
318 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
319
320 switch (geomClass)
321 {
322 case dSphereClass:
323 if (((dxTriMesh*)g)->doSphereTC)
324 return 1;
325 break;
326 case dBoxClass:
327 if (((dxTriMesh*)g)->doBoxTC)
328 return 1;
329 break;
330 case dCapsuleClass:
331 if (((dxTriMesh*)g)->doCapsuleTC)
332 return 1;
333 break;
334 }
335 return 0;
336}
337
338void dGeomTriMeshClearTCCache(dGeomID g){
339 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
340
341 dxTriMesh* Geom = (dxTriMesh*)g;
342 Geom->ClearTCCache();
343}
344
345/*
346 * returns the TriMeshDataID
347 */
348dTriMeshDataID
349dGeomTriMeshGetTriMeshDataID(dGeomID g)
350{
351 dxTriMesh* Geom = (dxTriMesh*) g;
352 return Geom->Data;
353}
354
355// Getting data
356void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2)
357{
358 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
359
360 dxTriMesh* Geom = (dxTriMesh*)g;
361 gim_trimesh_locks_work_data(&Geom->m_collision_trimesh);
362 gim_trimesh_get_triangle_vertices(&Geom->m_collision_trimesh, Index, (*v0),(*v1),(*v2));
363 gim_trimesh_unlocks_work_data(&Geom->m_collision_trimesh);
364
365}
366
367void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
368 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
369
370 dxTriMesh* Geom = (dxTriMesh*)g;
371 dVector3 dv[3];
372 gim_trimesh_locks_work_data(&Geom->m_collision_trimesh);
373 gim_trimesh_get_triangle_vertices(&Geom->m_collision_trimesh, Index, dv[0],dv[1],dv[2]);
374 GetPointFromBarycentric(dv, u, v, Out);
375 gim_trimesh_unlocks_work_data(&Geom->m_collision_trimesh);
376}
377
378int dGeomTriMeshGetTriangleCount (dGeomID g)
379{
380 dxTriMesh* Geom = (dxTriMesh*)g;
381 return gim_trimesh_get_triangle_count(&Geom->m_collision_trimesh);
382}
383
384void dGeomTriMeshDataUpdate(dTriMeshDataID g) {
385 dUASSERT(g, "argument not trimesh data");
386 g->UpdateData();
387}
388
389
390//
391// GIMPACT TRIMESH-TRIMESH COLLIDER
392//
393
394int dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
395{
396 dIASSERT (Stride >= (int)sizeof(dContactGeom));
397 dIASSERT (g1->type == dTriMeshClass);
398 dIASSERT (g2->type == dTriMeshClass);
399 dIASSERT ((Flags & NUMC_MASK) >= 1);
400
401 dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
402 dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
403 //Create contact list
404 GDYNAMIC_ARRAY trimeshcontacts;
405 GIM_CREATE_CONTACT_LIST(trimeshcontacts);
406
407 //Collide trimeshes
408 gim_trimesh_trimesh_collision(&TriMesh1->m_collision_trimesh,&TriMesh2->m_collision_trimesh,&trimeshcontacts);
409
410 if(trimeshcontacts.m_size == 0)
411 {
412 GIM_DYNARRAY_DESTROY(trimeshcontacts);
413 return 0;
414 }
415
416 GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
417
418
419 unsigned contactcount = trimeshcontacts.m_size;
420 unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK);
421 if (contactcount > maxcontacts)
422 {
423 contactcount = maxcontacts;
424 }
425
426 dContactGeom* pcontact;
427 unsigned i;
428
429 for (i=0;i<contactcount;i++)
430 {
431 pcontact = SAFECONTACT(Flags, Contacts, i, Stride);
432
433 pcontact->pos[0] = ptrimeshcontacts->m_point[0];
434 pcontact->pos[1] = ptrimeshcontacts->m_point[1];
435 pcontact->pos[2] = ptrimeshcontacts->m_point[2];
436 pcontact->pos[3] = 1.0f;
437
438 pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
439 pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
440 pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
441 pcontact->normal[3] = 0;
442
443 pcontact->depth = ptrimeshcontacts->m_depth;
444 pcontact->g1 = g1;
445 pcontact->g2 = g2;
446
447 ptrimeshcontacts++;
448 }
449
450 GIM_DYNARRAY_DESTROY(trimeshcontacts);
451
452 return (int)contactcount;
453}
454
455#endif // dTRIMESH_GIMPACT
456#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_internal.h b/libraries/ode-0.9/ode/src/collision_trimesh_internal.h
deleted file mode 100644
index bf474a2..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_internal.h
+++ /dev/null
@@ -1,495 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh code by Erwin de Vries.
24// Modified for FreeSOLID Compatibility by Rodrigo Hernandez
25
26#ifndef _ODE_COLLISION_TRIMESH_INTERNAL_H_
27#define _ODE_COLLISION_TRIMESH_INTERNAL_H_
28
29int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
30int dCollideTrimeshPlane(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
31
32int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
33int dCollideBTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
34int dCollideRTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
35int dCollideTTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
36int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
37
38PURE_INLINE int dCollideRayTrimesh( dxGeom *ray, dxGeom *trimesh, int flags,
39 dContactGeom *contact, int skip )
40{
41 // Swapped case, for code that needs it (heightfield initially)
42 // The other ray-geom colliders take geoms in a swapped order to the
43 // dCollideRTL function which is annoying when using function pointers.
44 return dCollideRTL( trimesh, ray, flags, contact, skip );
45}
46
47//****************************************************************************
48// dxTriMesh class
49
50#ifdef TRIMESH_INTERNAL
51
52#include "collision_kernel.h"
53#include <ode/collision_trimesh.h>
54
55#if dTRIMESH_OPCODE
56#define BAN_OPCODE_AUTOLINK
57#include "Opcode.h"
58using namespace Opcode;
59#endif // dTRIMESH_OPCODE
60
61#if dTRIMESH_GIMPACT
62#include <GIMPACT/gimpact.h>
63#endif
64
65struct dxTriMeshData : public dBase
66{
67 /* Array of flags for which edges and verts should be used on each triangle */
68 enum UseFlags
69 {
70 kEdge0 = 0x1,
71 kEdge1 = 0x2,
72 kEdge2 = 0x4,
73 kVert0 = 0x8,
74 kVert1 = 0x10,
75 kVert2 = 0x20,
76
77 kUseAll = 0xFF,
78 };
79
80 /* Setup the UseFlags array */
81 void Preprocess();
82 /* For when app changes the vertices */
83 void UpdateData();
84
85#if dTRIMESH_OPCODE
86 Model BVTree;
87 MeshInterface Mesh;
88
89 dxTriMeshData();
90 ~dxTriMeshData();
91
92 void Build(const void* Vertices, int VertexStide, int VertexCount,
93 const void* Indices, int IndexCount, int TriStride,
94 const void* Normals,
95 bool Single);
96
97 /* aabb in model space */
98 dVector3 AABBCenter;
99 dVector3 AABBExtents;
100
101 // data for use in collision resolution
102 const void* Normals;
103 uint8* UseFlags;
104#endif // dTRIMESH_OPCODE
105
106#if dTRIMESH_GIMPACT
107 const char* m_Vertices;
108 int m_VertexStride;
109 int m_VertexCount;
110 const char* m_Indices;
111 int m_TriangleCount;
112 int m_TriStride;
113 bool m_single;
114
115 dxTriMeshData()
116 {
117 m_Vertices=NULL;
118 m_VertexStride = 12;
119 m_VertexCount = 0;
120 m_Indices = 0;
121 m_TriangleCount = 0;
122 m_TriStride = 12;
123 m_single = true;
124 }
125
126 void Build(const void* Vertices, int VertexStride, int VertexCount,
127 const void* Indices, int IndexCount, int TriStride,
128 const void* Normals,
129 bool Single)
130 {
131 dIASSERT(Vertices);
132 dIASSERT(Indices);
133 dIASSERT(VertexStride);
134 dIASSERT(TriStride);
135 dIASSERT(IndexCount);
136 m_Vertices=(const char *)Vertices;
137 m_VertexStride = VertexStride;
138 m_VertexCount = VertexCount;
139 m_Indices = (const char *)Indices;
140 m_TriangleCount = IndexCount/3;
141 m_TriStride = TriStride;
142 m_single = Single;
143 }
144
145 inline void GetVertex(unsigned int i, dVector3 Out)
146 {
147 if(m_single)
148 {
149 const float * fverts = (const float * )(m_Vertices + m_VertexStride*i);
150 Out[0] = fverts[0];
151 Out[1] = fverts[1];
152 Out[2] = fverts[2];
153 Out[3] = 1.0f;
154 }
155 else
156 {
157 const double * dverts = (const double * )(m_Vertices + m_VertexStride*i);
158 Out[0] = (float)dverts[0];
159 Out[1] = (float)dverts[1];
160 Out[2] = (float)dverts[2];
161 Out[3] = 1.0f;
162
163 }
164 }
165
166 inline void GetTriIndices(unsigned int itriangle, unsigned int triindices[3])
167 {
168 const unsigned int * ind = (const unsigned int * )(m_Indices + m_TriStride*itriangle);
169 triindices[0] = ind[0];
170 triindices[1] = ind[1];
171 triindices[2] = ind[2];
172 }
173#endif // dTRIMESH_GIMPACT
174};
175
176
177struct dxTriMesh : public dxGeom{
178 // Callbacks
179 dTriCallback* Callback;
180 dTriArrayCallback* ArrayCallback;
181 dTriRayCallback* RayCallback;
182
183 // Data types
184 dxTriMeshData* Data;
185
186 bool doSphereTC;
187 bool doBoxTC;
188 bool doCapsuleTC;
189
190 // Functions
191 dxTriMesh(dSpaceID Space, dTriMeshDataID Data);
192 ~dxTriMesh();
193
194 void ClearTCCache();
195
196 int AABBTest(dxGeom* g, dReal aabb[6]);
197 void computeAABB();
198
199#if dTRIMESH_OPCODE
200 // Instance data for last transform.
201 dMatrix4 last_trans;
202
203 // Colliders
204 static PlanesCollider _PlanesCollider;
205 static SphereCollider _SphereCollider;
206 static OBBCollider _OBBCollider;
207 static RayCollider _RayCollider;
208 static AABBTreeCollider _AABBTreeCollider;
209 static LSSCollider _LSSCollider;
210
211 // Some constants
212 static CollisionFaces Faces;
213 // Temporal coherence
214 struct SphereTC : public SphereCache{
215 dxGeom* Geom;
216 };
217 dArray<SphereTC> SphereTCCache;
218 static SphereCache defaultSphereCache;
219
220 struct BoxTC : public OBBCache{
221 dxGeom* Geom;
222 };
223 dArray<BoxTC> BoxTCCache;
224 static OBBCache defaultBoxCache;
225
226 struct CapsuleTC : public LSSCache{
227 dxGeom* Geom;
228 };
229 dArray<CapsuleTC> CapsuleTCCache;
230 static LSSCache defaultCapsuleCache;
231#endif // dTRIMESH_OPCODE
232
233#if dTRIMESH_GIMPACT
234 GIM_TRIMESH m_collision_trimesh;
235#endif // dTRIMESH_GIMPACT
236};
237
238#if 0
239#include "collision_kernel.h"
240// Fetches a contact
241inline dContactGeom* SAFECONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){
242 dIASSERT(Index >= 0 && Index < (Flags & NUMC_MASK));
243 return ((dContactGeom*)(((char*)Contacts) + (Index * Stride)));
244}
245#endif
246
247#if dTRIMESH_OPCODE
248inline void FetchTriangle(dxTriMesh* TriMesh, int Index, dVector3 Out[3]){
249 VertexPointers VP;
250 TriMesh->Data->Mesh.GetTriangle(VP, Index);
251 for (int i = 0; i < 3; i++){
252 Out[i][0] = VP.Vertex[i]->x;
253 Out[i][1] = VP.Vertex[i]->y;
254 Out[i][2] = VP.Vertex[i]->z;
255 Out[i][3] = 0;
256 }
257}
258
259inline void FetchTriangle(dxTriMesh* TriMesh, int Index, const dVector3 Position, const dMatrix3 Rotation, dVector3 Out[3]){
260 VertexPointers VP;
261 TriMesh->Data->Mesh.GetTriangle(VP, Index);
262 for (int i = 0; i < 3; i++){
263 dVector3 v;
264 v[0] = VP.Vertex[i]->x;
265 v[1] = VP.Vertex[i]->y;
266 v[2] = VP.Vertex[i]->z;
267 v[3] = 0;
268
269 dMULTIPLY0_331(Out[i], Rotation, v);
270 Out[i][0] += Position[0];
271 Out[i][1] += Position[1];
272 Out[i][2] += Position[2];
273 Out[i][3] = 0;
274 }
275}
276
277inline Matrix4x4& MakeMatrix(const dVector3 Position, const dMatrix3 Rotation, Matrix4x4& Out){
278 Out.m[0][0] = (float) Rotation[0];
279 Out.m[1][0] = (float) Rotation[1];
280 Out.m[2][0] = (float) Rotation[2];
281
282 Out.m[0][1] = (float) Rotation[4];
283 Out.m[1][1] = (float) Rotation[5];
284 Out.m[2][1] = (float) Rotation[6];
285
286 Out.m[0][2] = (float) Rotation[8];
287 Out.m[1][2] = (float) Rotation[9];
288 Out.m[2][2] = (float) Rotation[10];
289
290 Out.m[3][0] = (float) Position[0];
291 Out.m[3][1] = (float) Position[1];
292 Out.m[3][2] = (float) Position[2];
293
294 Out.m[0][3] = 0.0f;
295 Out.m[1][3] = 0.0f;
296 Out.m[2][3] = 0.0f;
297 Out.m[3][3] = 1.0f;
298
299 return Out;
300}
301
302inline Matrix4x4& MakeMatrix(dxGeom* g, Matrix4x4& Out){
303 const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
304 const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
305 return MakeMatrix(Position, Rotation, Out);
306}
307#endif // dTRIMESH_OPCODE
308
309#if dTRIMESH_GIMPACT
310inline void FetchTriangle(dxTriMesh* TriMesh, int Index, const dVector3 Position, const dMatrix3 Rotation, dVector3 Out[3]){
311 // why is this not implemented?
312 dAASSERT(false);
313}
314
315inline void MakeMatrix(const dVector3 Position, const dMatrix3 Rotation, mat4f m)
316{
317 m[0][0] = (float) Rotation[0];
318 m[0][1] = (float) Rotation[1];
319 m[0][2] = (float) Rotation[2];
320
321 m[1][0] = (float) Rotation[4];
322 m[1][1] = (float) Rotation[5];
323 m[1][2] = (float) Rotation[6];
324
325 m[2][0] = (float) Rotation[8];
326 m[2][1] = (float) Rotation[9];
327 m[2][2] = (float) Rotation[10];
328
329 m[0][3] = (float) Position[0];
330 m[1][3] = (float) Position[1];
331 m[2][3] = (float) Position[2];
332
333}
334
335inline void MakeMatrix(dxGeom* g, mat4f Out){
336 const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
337 const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
338 MakeMatrix(Position, Rotation, Out);
339}
340#endif // dTRIMESH_GIMPACT
341
342// Outputs a matrix to 3 vectors
343inline void Decompose(const dMatrix3 Matrix, dVector3 Right, dVector3 Up, dVector3 Direction){
344 Right[0] = Matrix[0 * 4 + 0];
345 Right[1] = Matrix[1 * 4 + 0];
346 Right[2] = Matrix[2 * 4 + 0];
347 Right[3] = REAL(0.0);
348 Up[0] = Matrix[0 * 4 + 1];
349 Up[1] = Matrix[1 * 4 + 1];
350 Up[2] = Matrix[2 * 4 + 1];
351 Up[3] = REAL(0.0);
352 Direction[0] = Matrix[0 * 4 + 2];
353 Direction[1] = Matrix[1 * 4 + 2];
354 Direction[2] = Matrix[2 * 4 + 2];
355 Direction[3] = REAL(0.0);
356}
357
358// Outputs a matrix to 3 vectors
359inline void Decompose(const dMatrix3 Matrix, dVector3 Vectors[3]){
360 Decompose(Matrix, Vectors[0], Vectors[1], Vectors[2]);
361}
362
363// Finds barycentric
364inline void GetPointFromBarycentric(const dVector3 dv[3], dReal u, dReal v, dVector3 Out){
365 dReal w = REAL(1.0) - u - v;
366
367 Out[0] = (dv[0][0] * w) + (dv[1][0] * u) + (dv[2][0] * v);
368 Out[1] = (dv[0][1] * w) + (dv[1][1] * u) + (dv[2][1] * v);
369 Out[2] = (dv[0][2] * w) + (dv[1][2] * u) + (dv[2][2] * v);
370 Out[3] = (dv[0][3] * w) + (dv[1][3] * u) + (dv[2][3] * v);
371}
372
373// Performs a callback
374inline bool Callback(dxTriMesh* TriMesh, dxGeom* Object, int TriIndex){
375 if (TriMesh->Callback != NULL){
376 return (TriMesh->Callback(TriMesh, Object, TriIndex)!=0);
377 }
378 else return true;
379}
380
381// Some utilities
382template<class T> const T& dcMAX(const T& x, const T& y){
383 return x > y ? x : y;
384}
385
386template<class T> const T& dcMIN(const T& x, const T& y){
387 return x < y ? x : y;
388}
389
390dReal SqrDistancePointTri( const dVector3 p, const dVector3 triOrigin,
391 const dVector3 triEdge1, const dVector3 triEdge2,
392 dReal* pfSParam = 0, dReal* pfTParam = 0 );
393
394dReal SqrDistanceSegments( const dVector3 seg1Origin, const dVector3 seg1Direction,
395 const dVector3 seg2Origin, const dVector3 seg2Direction,
396 dReal* pfSegP0 = 0, dReal* pfSegP1 = 0 );
397
398dReal SqrDistanceSegTri( const dVector3 segOrigin, const dVector3 segEnd,
399 const dVector3 triOrigin,
400 const dVector3 triEdge1, const dVector3 triEdge2,
401 dReal* t = 0, dReal* u = 0, dReal* v = 0 );
402
403inline
404void Vector3Subtract( const dVector3 left, const dVector3 right, dVector3 result )
405{
406 result[0] = left[0] - right[0];
407 result[1] = left[1] - right[1];
408 result[2] = left[2] - right[2];
409 result[3] = REAL(0.0);
410}
411
412inline
413void Vector3Add( const dVector3 left, const dVector3 right, dVector3 result )
414{
415 result[0] = left[0] + right[0];
416 result[1] = left[1] + right[1];
417 result[2] = left[2] + right[2];
418 result[3] = REAL(0.0);
419}
420
421inline
422void Vector3Negate( const dVector3 in, dVector3 out )
423{
424 out[0] = -in[0];
425 out[1] = -in[1];
426 out[2] = -in[2];
427 out[3] = REAL(0.0);
428}
429
430inline
431void Vector3Copy( const dVector3 in, dVector3 out )
432{
433 out[0] = in[0];
434 out[1] = in[1];
435 out[2] = in[2];
436 out[3] = REAL(0.0);
437}
438
439inline
440void Vector3Multiply( const dVector3 in, dReal scalar, dVector3 out )
441{
442 out[0] = in[0] * scalar;
443 out[1] = in[1] * scalar;
444 out[2] = in[2] * scalar;
445 out[3] = REAL(0.0);
446}
447
448inline
449void TransformVector3( const dVector3 in,
450 const dMatrix3 orientation, const dVector3 position,
451 dVector3 out )
452{
453 dMULTIPLY0_331( out, orientation, in );
454 out[0] += position[0];
455 out[1] += position[1];
456 out[2] += position[2];
457}
458
459//------------------------------------------------------------------------------
460/**
461 @brief Check for intersection between triangle and capsule.
462
463 @param dist [out] Shortest distance squared between the triangle and
464 the capsule segment (central axis).
465 @param t [out] t value of point on segment that's the shortest distance
466 away from the triangle, the coordinates of this point
467 can be found by (cap.seg.end - cap.seg.start) * t,
468 or cap.seg.ipol(t).
469 @param u [out] Barycentric coord on triangle.
470 @param v [out] Barycentric coord on triangle.
471 @return True if intersection exists.
472
473 The third Barycentric coord is implicit, ie. w = 1.0 - u - v
474 The Barycentric coords give the location of the point on the triangle
475 closest to the capsule (where the distance between the two shapes
476 is the shortest).
477*/
478inline
479bool IntersectCapsuleTri( const dVector3 segOrigin, const dVector3 segEnd,
480 const dReal radius, const dVector3 triOrigin,
481 const dVector3 triEdge0, const dVector3 triEdge1,
482 dReal* dist, dReal* t, dReal* u, dReal* v )
483{
484 dReal sqrDist = SqrDistanceSegTri( segOrigin, segEnd, triOrigin, triEdge0, triEdge1,
485 t, u, v );
486
487 if ( dist )
488 *dist = sqrDist;
489
490 return ( sqrDist <= (radius * radius) );
491}
492
493#endif //TRIMESH_INTERNAL
494
495#endif //_ODE_COLLISION_TRIMESH_INTERNAL_H_
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_opcode.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_opcode.cpp
deleted file mode 100644
index 07f3f8a..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_opcode.cpp
+++ /dev/null
@@ -1,833 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh code by Erwin de Vries.
24
25#include <ode/collision.h>
26#include <ode/matrix.h>
27#include <ode/rotation.h>
28#include <ode/odemath.h>
29#include "collision_util.h"
30#define TRIMESH_INTERNAL
31#include "collision_trimesh_internal.h"
32
33#if dTRIMESH_ENABLED
34#if dTRIMESH_OPCODE
35
36// Trimesh data
37dxTriMeshData::dxTriMeshData() : UseFlags( NULL )
38{
39#if !dTRIMESH_ENABLED
40 dUASSERT(false, "dTRIMESH_ENABLED is not defined. Trimesh geoms will not work");
41#endif
42}
43
44dxTriMeshData::~dxTriMeshData()
45{
46 if ( UseFlags )
47 delete [] UseFlags;
48}
49
50void
51dxTriMeshData::Build(const void* Vertices, int VertexStide, int VertexCount,
52 const void* Indices, int IndexCount, int TriStride,
53 const void* in_Normals,
54 bool Single)
55{
56#if dTRIMESH_ENABLED
57
58 Mesh.SetNbTriangles(IndexCount / 3);
59 Mesh.SetNbVertices(VertexCount);
60 Mesh.SetPointers((IndexedTriangle*)Indices, (Point*)Vertices);
61 Mesh.SetStrides(TriStride, VertexStide);
62 Mesh.Single = Single;
63
64 // Build tree
65 BuildSettings Settings;
66 // recommended in Opcode User Manual
67 //Settings.mRules = SPLIT_COMPLETE | SPLIT_SPLATTERPOINTS | SPLIT_GEOMCENTER;
68 // used in ODE, why?
69 //Settings.mRules = SPLIT_BEST_AXIS;
70
71 // best compromise?
72 Settings.mRules = SPLIT_BEST_AXIS | SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER;
73
74
75 OPCODECREATE TreeBuilder;
76 TreeBuilder.mIMesh = &Mesh;
77
78 TreeBuilder.mSettings = Settings;
79 TreeBuilder.mNoLeaf = true;
80 TreeBuilder.mQuantized = false;
81
82 TreeBuilder.mKeepOriginal = false;
83 TreeBuilder.mCanRemap = false;
84
85
86
87 BVTree.Build(TreeBuilder);
88
89 // compute model space AABB
90 dVector3 AABBMax, AABBMin;
91 AABBMax[0] = AABBMax[1] = AABBMax[2] = (dReal) -dInfinity;
92 AABBMin[0] = AABBMin[1] = AABBMin[2] = (dReal) dInfinity;
93 if( Single ) {
94 const char* verts = (const char*)Vertices;
95 for( int i = 0; i < VertexCount; ++i ) {
96 const float* v = (const float*)verts;
97 if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
98 if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
99 if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
100 if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
101 if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
102 if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
103 verts += VertexStide;
104 }
105 } else {
106 const char* verts = (const char*)Vertices;
107 for( int i = 0; i < VertexCount; ++i ) {
108 const double* v = (const double*)verts;
109 if( v[0] > AABBMax[0] ) AABBMax[0] = (dReal) v[0];
110 if( v[1] > AABBMax[1] ) AABBMax[1] = (dReal) v[1];
111 if( v[2] > AABBMax[2] ) AABBMax[2] = (dReal) v[2];
112 if( v[0] < AABBMin[0] ) AABBMin[0] = (dReal) v[0];
113 if( v[1] < AABBMin[1] ) AABBMin[1] = (dReal) v[1];
114 if( v[2] < AABBMin[2] ) AABBMin[2] = (dReal) v[2];
115 verts += VertexStide;
116 }
117 }
118 AABBCenter[0] = (AABBMin[0] + AABBMax[0]) * REAL(0.5);
119 AABBCenter[1] = (AABBMin[1] + AABBMax[1]) * REAL(0.5);
120 AABBCenter[2] = (AABBMin[2] + AABBMax[2]) * REAL(0.5);
121 AABBExtents[0] = AABBMax[0] - AABBCenter[0];
122 AABBExtents[1] = AABBMax[1] - AABBCenter[1];
123 AABBExtents[2] = AABBMax[2] - AABBCenter[2];
124
125 // user data (not used by OPCODE)
126 Normals = (dReal *) in_Normals;
127
128 UseFlags = 0;
129
130#endif // dTRIMESH_ENABLED
131}
132
133struct EdgeRecord
134{
135 int VertIdx1; // Index into vertex array for this edges vertices
136 int VertIdx2;
137 int TriIdx; // Index into triangle array for triangle this edge belongs to
138
139 uint8 EdgeFlags;
140 uint8 Vert1Flags;
141 uint8 Vert2Flags;
142 bool Concave;
143};
144
145// Edge comparison function for qsort
146static int EdgeCompare(const void* edge1, const void* edge2)
147{
148 EdgeRecord* e1 = (EdgeRecord*)edge1;
149 EdgeRecord* e2 = (EdgeRecord*)edge2;
150
151 if (e1->VertIdx1 == e2->VertIdx1)
152 return e1->VertIdx2 - e2->VertIdx2;
153 else
154 return e1->VertIdx1 - e2->VertIdx1;
155}
156
157void SetupEdge(EdgeRecord* edge, int edgeIdx, int triIdx, const unsigned int* vertIdxs)
158{
159 if (edgeIdx == 0)
160 {
161 edge->EdgeFlags = dxTriMeshData::kEdge0;
162 edge->Vert1Flags = dxTriMeshData::kVert0;
163 edge->Vert2Flags = dxTriMeshData::kVert1;
164 edge->VertIdx1 = vertIdxs[0];
165 edge->VertIdx2 = vertIdxs[1];
166 }
167 else if (edgeIdx == 1)
168 {
169 edge->EdgeFlags = dxTriMeshData::kEdge1;
170 edge->Vert1Flags = dxTriMeshData::kVert1;
171 edge->Vert2Flags = dxTriMeshData::kVert2;
172 edge->VertIdx1 = vertIdxs[1];
173 edge->VertIdx2 = vertIdxs[2];
174 }
175 else if (edgeIdx == 2)
176 {
177 edge->EdgeFlags = dxTriMeshData::kEdge2;
178 edge->Vert1Flags = dxTriMeshData::kVert2;
179 edge->Vert2Flags = dxTriMeshData::kVert0;
180 edge->VertIdx1 = vertIdxs[2];
181 edge->VertIdx2 = vertIdxs[0];
182 }
183
184 // Make sure vert index 1 is less than index 2 (for easier sorting)
185 if (edge->VertIdx1 > edge->VertIdx2)
186 {
187 unsigned int tempIdx = edge->VertIdx1;
188 edge->VertIdx1 = edge->VertIdx2;
189 edge->VertIdx2 = tempIdx;
190
191 uint8 tempFlags = edge->Vert1Flags;
192 edge->Vert1Flags = edge->Vert2Flags;
193 edge->Vert2Flags = tempFlags;
194 }
195
196 edge->TriIdx = triIdx;
197 edge->Concave = false;
198}
199
200#if dTRIMESH_ENABLED
201
202// Get the vertex opposite this edge in the triangle
203inline Point GetOppositeVert(EdgeRecord* edge, const Point* vertices[])
204{
205 if ((edge->Vert1Flags == dxTriMeshData::kVert0 && edge->Vert2Flags == dxTriMeshData::kVert1) ||
206 (edge->Vert1Flags == dxTriMeshData::kVert1 && edge->Vert2Flags == dxTriMeshData::kVert0))
207 {
208 return *vertices[2];
209 }
210 else if ((edge->Vert1Flags == dxTriMeshData::kVert1 && edge->Vert2Flags == dxTriMeshData::kVert2) ||
211 (edge->Vert1Flags == dxTriMeshData::kVert2 && edge->Vert2Flags == dxTriMeshData::kVert1))
212 {
213 return *vertices[0];
214 }
215 else
216 return *vertices[1];
217}
218
219#endif // dTRIMESH_ENABLED
220
221void dxTriMeshData::Preprocess()
222{
223
224#if dTRIMESH_ENABLED
225
226 // If this mesh has already been preprocessed, exit
227 if (UseFlags)
228 return;
229
230 udword numTris = Mesh.GetNbTriangles();
231 udword numEdges = numTris * 3;
232
233 UseFlags = new uint8[numTris];
234 memset(UseFlags, 0, sizeof(uint8) * numTris);
235
236 EdgeRecord* records = new EdgeRecord[numEdges];
237
238 // Make a list of every edge in the mesh
239 const IndexedTriangle* tris = Mesh.GetTris();
240 for (unsigned int i = 0; i < numTris; i++)
241 {
242 SetupEdge(&records[i*3], 0, i, tris->mVRef);
243 SetupEdge(&records[i*3+1], 1, i, tris->mVRef);
244 SetupEdge(&records[i*3+2], 2, i, tris->mVRef);
245
246 tris = (const IndexedTriangle*)(((uint8*)tris) + Mesh.GetTriStride());
247 }
248
249 // Sort the edges, so the ones sharing the same verts are beside each other
250 qsort(records, numEdges, sizeof(EdgeRecord), EdgeCompare);
251
252 // Go through the sorted list of edges and flag all the edges and vertices that we need to use
253 for (unsigned int i = 0; i < numEdges; i++)
254 {
255 EdgeRecord* rec1 = &records[i];
256 EdgeRecord* rec2 = 0;
257 if (i < numEdges - 1)
258 rec2 = &records[i+1];
259
260 if (rec2 &&
261 rec1->VertIdx1 == rec2->VertIdx1 &&
262 rec1->VertIdx2 == rec2->VertIdx2)
263 {
264 VertexPointers vp;
265 Mesh.GetTriangle(vp, rec1->TriIdx);
266
267 // Get the normal of the first triangle
268 Point triNorm = (*vp.Vertex[2] - *vp.Vertex[1]) ^ (*vp.Vertex[0] - *vp.Vertex[1]);
269 triNorm.Normalize();
270
271 // Get the vert opposite this edge in the first triangle
272 Point oppositeVert1 = GetOppositeVert(rec1, vp.Vertex);
273
274 // Get the vert opposite this edge in the second triangle
275 Mesh.GetTriangle(vp, rec2->TriIdx);
276 Point oppositeVert2 = GetOppositeVert(rec2, vp.Vertex);
277
278 float dot = triNorm.Dot((oppositeVert2 - oppositeVert1).Normalize());
279
280 // We let the dot threshold for concavity get slightly negative to allow for rounding errors
281 static const float kConcaveThresh = -0.000001f;
282
283 // This is a concave edge, leave it for the next pass
284 if (dot >= kConcaveThresh)
285 rec1->Concave = true;
286 // If this is a convex edge, mark its vertices and edge as used
287 else
288 UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;
289
290 // Skip the second edge
291 i++;
292 }
293 // This is a boundary edge
294 else
295 {
296 UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;
297 }
298 }
299
300 // Go through the list once more, and take any edge we marked as concave and
301 // clear it's vertices flags in any triangles they're used in
302 for (unsigned int i = 0; i < numEdges; i++)
303 {
304 EdgeRecord& er = records[i];
305
306 if (er.Concave)
307 {
308 for (unsigned int j = 0; j < numEdges; j++)
309 {
310 EdgeRecord& curER = records[j];
311
312 if (curER.VertIdx1 == er.VertIdx1 ||
313 curER.VertIdx1 == er.VertIdx2)
314 UseFlags[curER.TriIdx] &= ~curER.Vert1Flags;
315
316 if (curER.VertIdx2 == er.VertIdx1 ||
317 curER.VertIdx2 == er.VertIdx2)
318 UseFlags[curER.TriIdx] &= ~curER.Vert2Flags;
319 }
320 }
321 }
322
323 delete [] records;
324
325#endif // dTRIMESH_ENABLED
326
327}
328
329dTriMeshDataID dGeomTriMeshDataCreate(){
330 return new dxTriMeshData();
331}
332
333void dGeomTriMeshDataDestroy(dTriMeshDataID g){
334 delete g;
335}
336
337
338
339
340void dGeomTriMeshSetLastTransform( dxGeom* g, dMatrix4 last_trans )
341{
342 dAASSERT(g)
343 dUASSERT(g->type == dTriMeshClass, "geom not trimesh");
344
345 for (int i=0; i<16; i++)
346 (((dxTriMesh*)g)->last_trans)[ i ] = last_trans[ i ];
347
348 return;
349}
350
351
352dReal* dGeomTriMeshGetLastTransform( dxGeom* g )
353{
354 dAASSERT(g)
355 dUASSERT(g->type == dTriMeshClass, "geom not trimesh");
356
357 return (dReal*)(((dxTriMesh*)g)->last_trans);
358}
359
360
361
362
363void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data)
364{
365 dUASSERT(g, "argument not trimesh data");
366
367 switch (data_id)
368 {
369 case TRIMESH_FACE_NORMALS:
370 g->Normals = (dReal *) in_data;
371 break;
372
373 default:
374 dUASSERT(data_id, "invalid data type");
375 break;
376 }
377
378 return;
379}
380
381
382
383void* dGeomTriMeshDataGet(dTriMeshDataID g, int data_id)
384{
385 dUASSERT(g, "argument not trimesh data");
386
387 switch (data_id)
388 {
389 case TRIMESH_FACE_NORMALS:
390 return (void *) g->Normals;
391 break;
392
393 default:
394 dUASSERT(data_id, "invalid data type");
395 break;
396 }
397
398 return NULL;
399}
400
401
402void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
403 const void* Vertices, int VertexStride, int VertexCount,
404 const void* Indices, int IndexCount, int TriStride,
405 const void* Normals)
406{
407 dUASSERT(g, "argument not trimesh data");
408
409 g->Build(Vertices, VertexStride, VertexCount,
410 Indices, IndexCount, TriStride,
411 Normals,
412 true);
413}
414
415
416void dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
417 const void* Vertices, int VertexStride, int VertexCount,
418 const void* Indices, int IndexCount, int TriStride)
419{
420 dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount,
421 Indices, IndexCount, TriStride, (void*)NULL);
422}
423
424
425void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g,
426 const void* Vertices, int VertexStride, int VertexCount,
427 const void* Indices, int IndexCount, int TriStride,
428 const void* Normals)
429{
430 dUASSERT(g, "argument not trimesh data");
431
432 g->Build(Vertices, VertexStride, VertexCount,
433 Indices, IndexCount, TriStride,
434 Normals,
435 false);
436}
437
438
439void dGeomTriMeshDataBuildDouble(dTriMeshDataID g,
440 const void* Vertices, int VertexStride, int VertexCount,
441 const void* Indices, int IndexCount, int TriStride) {
442 dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount,
443 Indices, IndexCount, TriStride, NULL);
444}
445
446
447void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
448 const dReal* Vertices, int VertexCount,
449 const int* Indices, int IndexCount,
450 const int* Normals){
451#ifdef dSINGLE
452 dGeomTriMeshDataBuildSingle1(g,
453 Vertices, 4 * sizeof(dReal), VertexCount,
454 Indices, IndexCount, 3 * sizeof(unsigned int),
455 Normals);
456#else
457 dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount,
458 Indices, IndexCount, 3 * sizeof(unsigned int),
459 Normals);
460#endif
461}
462
463
464void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
465 const dReal* Vertices, int VertexCount,
466 const int* Indices, int IndexCount) {
467 dGeomTriMeshDataBuildSimple1(g,
468 Vertices, VertexCount, Indices, IndexCount,
469 (const int*)NULL);
470}
471
472void dGeomTriMeshDataPreprocess(dTriMeshDataID g)
473{
474 dUASSERT(g, "argument not trimesh data");
475 g->Preprocess();
476}
477
478void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen)
479{
480 dUASSERT(g, "argument not trimesh data");
481#if dTRIMESH_ENABLED
482 *buf = g->UseFlags;
483 *bufLen = g->Mesh.GetNbTriangles();
484#endif // dTRIMESH_ENABLED
485}
486
487void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf)
488{
489 dUASSERT(g, "argument not trimesh data");
490 g->UseFlags = buf;
491}
492
493
494#if dTRIMESH_ENABLED
495
496// Trimesh Class Statics
497PlanesCollider dxTriMesh::_PlanesCollider;
498SphereCollider dxTriMesh::_SphereCollider;
499OBBCollider dxTriMesh::_OBBCollider;
500RayCollider dxTriMesh::_RayCollider;
501AABBTreeCollider dxTriMesh::_AABBTreeCollider;
502LSSCollider dxTriMesh::_LSSCollider;
503
504SphereCache dxTriMesh::defaultSphereCache;
505OBBCache dxTriMesh::defaultBoxCache;
506LSSCache dxTriMesh::defaultCapsuleCache;
507
508CollisionFaces dxTriMesh::Faces;
509
510#endif // dTRIMESH_ENABLED
511
512
513dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1)
514{
515 type = dTriMeshClass;
516
517 this->Data = Data;
518
519#if dTRIMESH_ENABLED
520
521 _RayCollider.SetDestination(&Faces);
522
523 _PlanesCollider.SetTemporalCoherence(true);
524
525 _SphereCollider.SetTemporalCoherence(true);
526 _SphereCollider.SetPrimitiveTests(false);
527
528 _OBBCollider.SetTemporalCoherence(true);
529
530 // no first-contact test (i.e. return full contact info)
531 _AABBTreeCollider.SetFirstContact( false );
532 // temporal coherence only works with "first conact" tests
533 _AABBTreeCollider.SetTemporalCoherence(false);
534 // Perform full BV-BV tests (true) or SAT-lite tests (false)
535 _AABBTreeCollider.SetFullBoxBoxTest( true );
536 // Perform full Primitive-BV tests (true) or SAT-lite tests (false)
537 _AABBTreeCollider.SetFullPrimBoxTest( true );
538 _LSSCollider.SetTemporalCoherence(false);
539
540#endif // dTRIMESH_ENABLED
541
542 /* TC has speed/space 'issues' that don't make it a clear
543 win by default on spheres/boxes. */
544 this->doSphereTC = false;
545 this->doBoxTC = false;
546 this->doCapsuleTC = false;
547
548#if dTRIMESH_ENABLED
549
550 const char* msg;
551 if ((msg =_AABBTreeCollider.ValidateSettings()))
552 dDebug (d_ERR_UASSERT, msg, " (%s:%d)", __FILE__,__LINE__);
553 _LSSCollider.SetPrimitiveTests(false);
554 _LSSCollider.SetFirstContact(false);
555
556#endif // dTRIMESH_ENABLED
557
558 for (int i=0; i<16; i++)
559 last_trans[i] = REAL( 0.0 );
560}
561
562dxTriMesh::~dxTriMesh(){
563 //
564}
565
566// Cleanup for allocations when shutting down ODE
567void opcode_collider_cleanup()
568{
569#if dTRIMESH_ENABLED
570
571 // Clear TC caches
572 dxTriMesh::Faces.Empty();
573 dxTriMesh::defaultSphereCache.TouchedPrimitives.Empty();
574 dxTriMesh::defaultBoxCache.TouchedPrimitives.Empty();
575 dxTriMesh::defaultCapsuleCache.TouchedPrimitives.Empty();
576
577#endif // dTRIMESH_ENABLED
578}
579
580
581
582void dxTriMesh::ClearTCCache()
583{
584#if dTRIMESH_ENABLED
585 /* dxTriMesh::ClearTCCache uses dArray's setSize(0) to clear the caches -
586 but the destructor isn't called when doing this, so we would leak.
587 So, call the previous caches' containers' destructors by hand first. */
588 int i, n;
589 n = SphereTCCache.size();
590 for( i = 0; i < n; ++i ) {
591 SphereTCCache[i].~SphereTC();
592 }
593 SphereTCCache.setSize(0);
594 n = BoxTCCache.size();
595 for( i = 0; i < n; ++i ) {
596 BoxTCCache[i].~BoxTC();
597 }
598 BoxTCCache.setSize(0);
599 n = CapsuleTCCache.size();
600 for( i = 0; i < n; ++i ) {
601 CapsuleTCCache[i].~CapsuleTC();
602 }
603 CapsuleTCCache.setSize(0);
604#endif // dTRIMESH_ENABLED
605}
606
607
608int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
609 return 1;
610}
611
612
613void dxTriMesh::computeAABB() {
614 const dxTriMeshData* d = Data;
615 dVector3 c;
616 const dMatrix3& R = final_posr->R;
617 const dVector3& pos = final_posr->pos;
618
619 dMULTIPLY0_331( c, R, d->AABBCenter );
620
621 dReal xrange = dFabs(R[0] * Data->AABBExtents[0]) +
622 dFabs(R[1] * Data->AABBExtents[1]) +
623 dFabs(R[2] * Data->AABBExtents[2]);
624 dReal yrange = dFabs(R[4] * Data->AABBExtents[0]) +
625 dFabs(R[5] * Data->AABBExtents[1]) +
626 dFabs(R[6] * Data->AABBExtents[2]);
627 dReal zrange = dFabs(R[8] * Data->AABBExtents[0]) +
628 dFabs(R[9] * Data->AABBExtents[1]) +
629 dFabs(R[10] * Data->AABBExtents[2]);
630
631 aabb[0] = c[0] + pos[0] - xrange;
632 aabb[1] = c[0] + pos[0] + xrange;
633 aabb[2] = c[1] + pos[1] - yrange;
634 aabb[3] = c[1] + pos[1] + yrange;
635 aabb[4] = c[2] + pos[2] - zrange;
636 aabb[5] = c[2] + pos[2] + zrange;
637}
638
639
640void dxTriMeshData::UpdateData()
641{
642#if dTRIMESH_ENABLED
643 BVTree.Refit();
644#endif // dTRIMESH_ENABLED
645}
646
647
648dGeomID dCreateTriMesh(dSpaceID space,
649 dTriMeshDataID Data,
650 dTriCallback* Callback,
651 dTriArrayCallback* ArrayCallback,
652 dTriRayCallback* RayCallback)
653{
654 dxTriMesh* Geom = new dxTriMesh(space, Data);
655 Geom->Callback = Callback;
656 Geom->ArrayCallback = ArrayCallback;
657 Geom->RayCallback = RayCallback;
658
659 return Geom;
660}
661
662void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback)
663{
664 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
665 ((dxTriMesh*)g)->Callback = Callback;
666}
667
668dTriCallback* dGeomTriMeshGetCallback(dGeomID g)
669{
670 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
671 return ((dxTriMesh*)g)->Callback;
672}
673
674void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback)
675{
676 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
677 ((dxTriMesh*)g)->ArrayCallback = ArrayCallback;
678}
679
680dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g)
681{
682 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
683 return ((dxTriMesh*)g)->ArrayCallback;
684}
685
686void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback)
687{
688 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
689 ((dxTriMesh*)g)->RayCallback = Callback;
690}
691
692dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g)
693{
694 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
695 return ((dxTriMesh*)g)->RayCallback;
696}
697
698void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data)
699{
700 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
701 ((dxTriMesh*)g)->Data = Data;
702 // I changed my data -- I know nothing about my own AABB anymore.
703 ((dxTriMesh*)g)->gflags |= (GEOM_DIRTY|GEOM_AABB_BAD);
704}
705
706dTriMeshDataID dGeomTriMeshGetData(dGeomID g)
707{
708 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
709 return ((dxTriMesh*)g)->Data;
710}
711
712
713
714void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable)
715{
716 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
717
718 switch (geomClass)
719 {
720 case dSphereClass:
721 ((dxTriMesh*)g)->doSphereTC = (1 == enable);
722 break;
723 case dBoxClass:
724 ((dxTriMesh*)g)->doBoxTC = (1 == enable);
725 break;
726 case dCapsuleClass:
727 ((dxTriMesh*)g)->doCapsuleTC = (1 == enable);
728 break;
729 }
730}
731
732int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass)
733{
734 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
735
736 switch (geomClass)
737 {
738 case dSphereClass:
739 if (((dxTriMesh*)g)->doSphereTC)
740 return 1;
741 break;
742 case dBoxClass:
743 if (((dxTriMesh*)g)->doBoxTC)
744 return 1;
745 break;
746 case dCapsuleClass:
747 if (((dxTriMesh*)g)->doCapsuleTC)
748 return 1;
749 break;
750 }
751 return 0;
752}
753
754void dGeomTriMeshClearTCCache(dGeomID g){
755 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
756
757 dxTriMesh* Geom = (dxTriMesh*)g;
758 Geom->ClearTCCache();
759}
760
761/*
762 * returns the TriMeshDataID
763 */
764dTriMeshDataID
765dGeomTriMeshGetTriMeshDataID(dGeomID g)
766{
767 dxTriMesh* Geom = (dxTriMesh*) g;
768 return Geom->Data;
769}
770
771// Getting data
772void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2){
773 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
774
775 dxTriMesh* Geom = (dxTriMesh*)g;
776
777 const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
778 const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
779
780 dVector3 v[3];
781 FetchTriangle(Geom, Index, Position, Rotation, v);
782
783 if (v0){
784 (*v0)[0] = v[0][0];
785 (*v0)[1] = v[0][1];
786 (*v0)[2] = v[0][2];
787 (*v0)[3] = v[0][3];
788 }
789 if (v1){
790 (*v1)[0] = v[1][0];
791 (*v1)[1] = v[1][1];
792 (*v1)[2] = v[1][2];
793 (*v1)[3] = v[1][3];
794 }
795 if (v2){
796 (*v2)[0] = v[2][0];
797 (*v2)[1] = v[2][1];
798 (*v2)[2] = v[2][2];
799 (*v2)[3] = v[2][3];
800 }
801}
802
803void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
804 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
805
806 dxTriMesh* Geom = (dxTriMesh*)g;
807
808 const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
809 const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
810
811 dVector3 dv[3];
812 FetchTriangle(Geom, Index, Position, Rotation, dv);
813
814 GetPointFromBarycentric(dv, u, v, Out);
815}
816
817int dGeomTriMeshGetTriangleCount (dGeomID g)
818{
819#if dTRIMESH_ENABLED
820 dxTriMesh* Geom = (dxTriMesh*)g;
821 return Geom->Data->Mesh.GetNbTriangles();
822#else
823 return 0;
824#endif // dTRIMESH_ENABLED
825}
826
827void dGeomTriMeshDataUpdate(dTriMeshDataID g) {
828 dUASSERT(g, "argument not trimesh data");
829 g->UpdateData();
830}
831
832#endif // dTRIMESH_OPCODE
833#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_plane.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_plane.cpp
deleted file mode 100644
index 54034aa..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_plane.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh - Plane collider by David Walters, July 2006
24
25#include <ode/collision.h>
26#include <ode/matrix.h>
27#include <ode/rotation.h>
28#include <ode/odemath.h>
29
30#if dTRIMESH_ENABLED
31
32#include "collision_util.h"
33#include "collision_std.h"
34
35#define TRIMESH_INTERNAL
36#include "collision_trimesh_internal.h"
37
38#if dTRIMESH_OPCODE
39int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
40{
41 dIASSERT( skip >= (int)sizeof( dContactGeom ) );
42 dIASSERT( o1->type == dTriMeshClass );
43 dIASSERT( o2->type == dPlaneClass );
44 dIASSERT ((flags & NUMC_MASK) >= 1);
45
46 // Alias pointers to the plane and trimesh
47 dxTriMesh* trimesh = (dxTriMesh*)( o1 );
48 dxPlane* plane = (dxPlane*)( o2 );
49
50 int contact_count = 0;
51
52 // Cache the maximum contact count.
53 const int contact_max = ( flags & NUMC_MASK );
54
55 // Cache trimesh position and rotation.
56 const dVector3& trimesh_pos = *(const dVector3*)dGeomGetPosition( trimesh );
57 const dMatrix3& trimesh_R = *(const dMatrix3*)dGeomGetRotation( trimesh );
58
59 //
60 // For all triangles.
61 //
62
63 // Cache the triangle count.
64 const int tri_count = trimesh->Data->Mesh.GetNbTriangles();
65
66 VertexPointers VP;
67 dReal alpha;
68 dVector3 vertex;
69
70#if !defined(dSINGLE) || 1
71 dVector3 int_vertex; // Intermediate vertex for double precision mode.
72#endif // dSINGLE
73
74 // For each triangle
75 for ( int t = 0; t < tri_count; ++t )
76 {
77 // Get triangle, which should also use callback.
78 trimesh->Data->Mesh.GetTriangle( VP, t );
79
80 // For each vertex.
81 for ( int v = 0; v < 3; ++v )
82 {
83 //
84 // Get Vertex
85 //
86
87#if defined(dSINGLE) && 0 // Always assign via intermediate array as otherwise it is an incapsulation violation
88
89 dMULTIPLY0_331( vertex, trimesh_R, (float*)( VP.Vertex[ v ] ) );
90
91#else // dDOUBLE || 1
92
93 // OPCODE data is in single precision format.
94 int_vertex[ 0 ] = VP.Vertex[ v ]->x;
95 int_vertex[ 1 ] = VP.Vertex[ v ]->y;
96 int_vertex[ 2 ] = VP.Vertex[ v ]->z;
97
98 dMULTIPLY0_331( vertex, trimesh_R, int_vertex );
99
100#endif // dSINGLE/dDOUBLE
101
102 vertex[ 0 ] += trimesh_pos[ 0 ];
103 vertex[ 1 ] += trimesh_pos[ 1 ];
104 vertex[ 2 ] += trimesh_pos[ 2 ];
105
106
107 //
108 // Collision?
109 //
110
111 // If alpha < 0 then point is if front of plane. i.e. no contact
112 // If alpha = 0 then the point is on the plane
113 alpha = plane->p[ 3 ] - dDOT( plane->p, vertex );
114
115 // If alpha > 0 the point is behind the plane. CONTACT!
116 if ( alpha > 0 )
117 {
118 // Alias the contact
119 dContactGeom* contact = SAFECONTACT( flags, contacts, contact_count, skip );
120
121 contact->pos[ 0 ] = vertex[ 0 ];
122 contact->pos[ 1 ] = vertex[ 1 ];
123 contact->pos[ 2 ] = vertex[ 2 ];
124
125 contact->normal[ 0 ] = plane->p[ 0 ];
126 contact->normal[ 1 ] = plane->p[ 1 ];
127 contact->normal[ 2 ] = plane->p[ 2 ];
128
129 contact->depth = alpha;
130 contact->g1 = plane;
131 contact->g2 = trimesh;
132
133 ++contact_count;
134
135 // All contact slots are full?
136 if ( contact_count >= contact_max )
137 return contact_count; // <=== STOP HERE
138 }
139 }
140 }
141
142 // Return contact count.
143 return contact_count;
144}
145#endif // dTRIMESH_OPCODE
146
147#if dTRIMESH_GIMPACT
148int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
149{
150 dIASSERT( skip >= (int)sizeof( dContactGeom ) );
151 dIASSERT( o1->type == dTriMeshClass );
152 dIASSERT( o2->type == dPlaneClass );
153 dIASSERT ((flags & NUMC_MASK) >= 1);
154
155 // Alias pointers to the plane and trimesh
156 dxTriMesh* trimesh = (dxTriMesh*)( o1 );
157 vec4f plane;
158 dGeomPlaneGetParams(o2, plane);
159
160 //Find collision
161
162 GDYNAMIC_ARRAY collision_result;
163 GIM_CREATE_TRIMESHPLANE_CONTACTS(collision_result);
164
165 gim_trimesh_plane_collision(&trimesh->m_collision_trimesh,plane,&collision_result);
166
167 if(collision_result.m_size == 0 )
168 {
169 GIM_DYNARRAY_DESTROY(collision_result);
170 return 0;
171 }
172
173
174 unsigned int contactcount = collision_result.m_size;
175 unsigned int contactmax = (unsigned int)(flags & NUMC_MASK);
176 if (contactcount > contactmax)
177 {
178 contactcount = contactmax;
179 }
180
181 dContactGeom* pcontact;
182 vec4f * planecontact_results = GIM_DYNARRAY_POINTER(vec4f,collision_result);
183
184 for(unsigned int i = 0; i < contactcount; i++ )
185 {
186 pcontact = SAFECONTACT(flags, contacts, i, skip);
187
188 pcontact->pos[0] = (*planecontact_results)[0];
189 pcontact->pos[1] = (*planecontact_results)[1];
190 pcontact->pos[2] = (*planecontact_results)[2];
191 pcontact->pos[3] = REAL(1.0);
192
193 pcontact->normal[0] = plane[0];
194 pcontact->normal[1] = plane[1];
195 pcontact->normal[2] = plane[2];
196 pcontact->normal[3] = 0;
197
198 pcontact->depth = (*planecontact_results)[3];
199 pcontact->g1 = o1;
200 pcontact->g2 = o2;
201
202 planecontact_results++;
203 }
204
205 GIM_DYNARRAY_DESTROY(collision_result);
206
207 return (int)contactcount;
208}
209#endif // dTRIMESH_GIMPACT
210
211
212#endif // dTRIMESH_ENABLED
213
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_ray.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_ray.cpp
deleted file mode 100644
index c0b97ca..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_ray.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh code by Erwin de Vries.
24
25#include <ode/collision.h>
26#include <ode/matrix.h>
27#include <ode/rotation.h>
28#include <ode/odemath.h>
29
30#if dTRIMESH_ENABLED
31
32#include "collision_util.h"
33
34#define TRIMESH_INTERNAL
35#include "collision_trimesh_internal.h"
36
37#if dTRIMESH_OPCODE
38int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride){
39 dIASSERT (Stride >= (int)sizeof(dContactGeom));
40 dIASSERT (g1->type == dTriMeshClass);
41 dIASSERT (RayGeom->type == dRayClass);
42 dIASSERT ((Flags & NUMC_MASK) >= 1);
43
44 dxTriMesh* TriMesh = (dxTriMesh*)g1;
45
46 const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh);
47 const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh);
48
49 RayCollider& Collider = TriMesh->_RayCollider;
50
51 dReal Length = dGeomRayGetLength(RayGeom);
52
53 int FirstContact, BackfaceCull;
54 dGeomRayGetParams(RayGeom, &FirstContact, &BackfaceCull);
55 int ClosestHit = dGeomRayGetClosestHit(RayGeom);
56
57 Collider.SetFirstContact(FirstContact != 0);
58 Collider.SetClosestHit(ClosestHit != 0);
59 Collider.SetCulling(BackfaceCull != 0);
60 Collider.SetMaxDist(Length);
61
62 dVector3 Origin, Direction;
63 dGeomRayGet(RayGeom, Origin, Direction);
64
65 /* Make Ray */
66 Ray WorldRay;
67 WorldRay.mOrig.x = Origin[0];
68 WorldRay.mOrig.y = Origin[1];
69 WorldRay.mOrig.z = Origin[2];
70 WorldRay.mDir.x = Direction[0];
71 WorldRay.mDir.y = Direction[1];
72 WorldRay.mDir.z = Direction[2];
73
74 /* Intersect */
75 Matrix4x4 amatrix;
76 int TriCount = 0;
77 if (Collider.Collide(WorldRay, TriMesh->Data->BVTree, &MakeMatrix(TLPosition, TLRotation, amatrix))) {
78 TriCount = TriMesh->Faces.GetNbFaces();
79 }
80
81 if (TriCount == 0) {
82 return 0;
83 }
84
85 const CollisionFace* Faces = TriMesh->Faces.GetFaces();
86
87 int OutTriCount = 0;
88 for (int i = 0; i < TriCount; i++) {
89 if (TriMesh->RayCallback == null ||
90 TriMesh->RayCallback(TriMesh, RayGeom, Faces[i].mFaceID,
91 Faces[i].mU, Faces[i].mV)) {
92 const int& TriIndex = Faces[i].mFaceID;
93 if (!Callback(TriMesh, RayGeom, TriIndex)) {
94 continue;
95 }
96
97 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride);
98
99 dVector3 dv[3];
100 FetchTriangle(TriMesh, TriIndex, TLPosition, TLRotation, dv);
101
102 // No sense to save on single type conversion in algorithm of this size.
103 // If there would be a custom typedef for distance type it could be used
104 // instead of dReal. However using float directly is the loss of abstraction
105 // and possible loss of precision in future.
106 /*float*/ dReal T = Faces[i].mDistance;
107 Contact->pos[0] = Origin[0] + (Direction[0] * T);
108 Contact->pos[1] = Origin[1] + (Direction[1] * T);
109 Contact->pos[2] = Origin[2] + (Direction[2] * T);
110 Contact->pos[3] = REAL(0.0);
111
112 dVector3 vu;
113 vu[0] = dv[1][0] - dv[0][0];
114 vu[1] = dv[1][1] - dv[0][1];
115 vu[2] = dv[1][2] - dv[0][2];
116 vu[3] = REAL(0.0);
117
118 dVector3 vv;
119 vv[0] = dv[2][0] - dv[0][0];
120 vv[1] = dv[2][1] - dv[0][1];
121 vv[2] = dv[2][2] - dv[0][2];
122 vv[3] = REAL(0.0);
123
124 dCROSS(Contact->normal, =, vv, vu); // Reversed
125
126 dNormalize3(Contact->normal);
127
128 Contact->depth = T;
129 Contact->g1 = TriMesh;
130 Contact->g2 = RayGeom;
131
132 OutTriCount++;
133
134 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
135 if (OutTriCount >= (Flags & NUMC_MASK)) {
136 break;
137 }
138 }
139 }
140 return OutTriCount;
141}
142#endif // dTRIMESH_OPCODE
143
144#if dTRIMESH_GIMPACT
145int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride)
146{
147 dIASSERT (Stride >= (int)sizeof(dContactGeom));
148 dIASSERT (g1->type == dTriMeshClass);
149 dIASSERT (RayGeom->type == dRayClass);
150 dIASSERT ((Flags & NUMC_MASK) >= 1);
151
152 dxTriMesh* TriMesh = (dxTriMesh*)g1;
153
154 dReal Length = dGeomRayGetLength(RayGeom);
155 int FirstContact, BackfaceCull;
156 dGeomRayGetParams(RayGeom, &FirstContact, &BackfaceCull);
157 int ClosestHit = dGeomRayGetClosestHit(RayGeom);
158 dVector3 Origin, Direction;
159 dGeomRayGet(RayGeom, Origin, Direction);
160
161 char intersect=0;
162 GIM_TRIANGLE_RAY_CONTACT_DATA contact_data;
163
164 if(ClosestHit)
165 {
166 intersect = gim_trimesh_ray_closest_collision(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data);
167 }
168 else
169 {
170 intersect = gim_trimesh_ray_collision(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data);
171 }
172
173 if(intersect == 0)
174 {
175 return 0;
176 }
177
178 int OutTriCount = 0;
179
180 if(!TriMesh->RayCallback ||
181 TriMesh->RayCallback(TriMesh, RayGeom, contact_data.m_face_id, contact_data.u , contact_data.v))
182 {
183 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, (OutTriCount-1), Stride);
184 VEC_COPY(Contact->pos,contact_data.m_point);
185 VEC_COPY(Contact->normal,contact_data.m_normal);
186 Contact->depth = contact_data.tparam;
187 Contact->g1 = TriMesh;
188 Contact->g2 = RayGeom;
189
190 OutTriCount = 1;
191 }
192
193 return OutTriCount;
194}
195#endif // dTRIMESH_GIMPACT
196
197#endif // dTRIMESH_ENABLED
198
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_sphere.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_sphere.cpp
deleted file mode 100644
index 7ee9b4b..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_sphere.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// TriMesh code by Erwin de Vries.
24
25#include <ode/collision.h>
26#include <ode/matrix.h>
27#include <ode/rotation.h>
28#include <ode/odemath.h>
29#include "collision_util.h"
30
31#if dTRIMESH_ENABLED
32
33#define TRIMESH_INTERNAL
34#include "collision_trimesh_internal.h"
35
36#if dTRIMESH_OPCODE
37#define MERGECONTACTS
38
39// Ripped from Opcode 1.1.
40static bool GetContactData(const dVector3& Center, dReal Radius, const dVector3 Origin, const dVector3 Edge0, const dVector3 Edge1, dReal& Dist, dReal& u, dReal& v){
41
42 // now onto the bulk of the collision...
43
44 dVector3 Diff;
45 Diff[0] = Origin[0] - Center[0];
46 Diff[1] = Origin[1] - Center[1];
47 Diff[2] = Origin[2] - Center[2];
48 Diff[3] = Origin[3] - Center[3];
49
50 dReal A00 = dDOT(Edge0, Edge0);
51 dReal A01 = dDOT(Edge0, Edge1);
52 dReal A11 = dDOT(Edge1, Edge1);
53
54 dReal B0 = dDOT(Diff, Edge0);
55 dReal B1 = dDOT(Diff, Edge1);
56
57 dReal C = dDOT(Diff, Diff);
58
59 dReal Det = dFabs(A00 * A11 - A01 * A01);
60 u = A01 * B1 - A11 * B0;
61 v = A01 * B0 - A00 * B1;
62
63 dReal DistSq;
64
65 if (u + v <= Det){
66 if(u < REAL(0.0)){
67 if(v < REAL(0.0)){ // region 4
68 if(B0 < REAL(0.0)){
69 v = REAL(0.0);
70 if (-B0 >= A00){
71 u = REAL(1.0);
72 DistSq = A00 + REAL(2.0) * B0 + C;
73 }
74 else{
75 u = -B0 / A00;
76 DistSq = B0 * u + C;
77 }
78 }
79 else{
80 u = REAL(0.0);
81 if(B1 >= REAL(0.0)){
82 v = REAL(0.0);
83 DistSq = C;
84 }
85 else if(-B1 >= A11){
86 v = REAL(1.0);
87 DistSq = A11 + REAL(2.0) * B1 + C;
88 }
89 else{
90 v = -B1 / A11;
91 DistSq = B1 * v + C;
92 }
93 }
94 }
95 else{ // region 3
96 u = REAL(0.0);
97 if(B1 >= REAL(0.0)){
98 v = REAL(0.0);
99 DistSq = C;
100 }
101 else if(-B1 >= A11){
102 v = REAL(1.0);
103 DistSq = A11 + REAL(2.0) * B1 + C;
104 }
105 else{
106 v = -B1 / A11;
107 DistSq = B1 * v + C;
108 }
109 }
110 }
111 else if(v < REAL(0.0)){ // region 5
112 v = REAL(0.0);
113 if (B0 >= REAL(0.0)){
114 u = REAL(0.0);
115 DistSq = C;
116 }
117 else if (-B0 >= A00){
118 u = REAL(1.0);
119 DistSq = A00 + REAL(2.0) * B0 + C;
120 }
121 else{
122 u = -B0 / A00;
123 DistSq = B0 * u + C;
124 }
125 }
126 else{ // region 0
127 // minimum at interior point
128 if (Det == REAL(0.0)){
129 u = REAL(0.0);
130 v = REAL(0.0);
131 DistSq = FLT_MAX;
132 }
133 else{
134 dReal InvDet = REAL(1.0) / Det;
135 u *= InvDet;
136 v *= InvDet;
137 DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
138 }
139 }
140 }
141 else{
142 dReal Tmp0, Tmp1, Numer, Denom;
143
144 if(u < REAL(0.0)){ // region 2
145 Tmp0 = A01 + B0;
146 Tmp1 = A11 + B1;
147 if (Tmp1 > Tmp0){
148 Numer = Tmp1 - Tmp0;
149 Denom = A00 - REAL(2.0) * A01 + A11;
150 if (Numer >= Denom){
151 u = REAL(1.0);
152 v = REAL(0.0);
153 DistSq = A00 + REAL(2.0) * B0 + C;
154 }
155 else{
156 u = Numer / Denom;
157 v = REAL(1.0) - u;
158 DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
159 }
160 }
161 else{
162 u = REAL(0.0);
163 if(Tmp1 <= REAL(0.0)){
164 v = REAL(1.0);
165 DistSq = A11 + REAL(2.0) * B1 + C;
166 }
167 else if(B1 >= REAL(0.0)){
168 v = REAL(0.0);
169 DistSq = C;
170 }
171 else{
172 v = -B1 / A11;
173 DistSq = B1 * v + C;
174 }
175 }
176 }
177 else if(v < REAL(0.0)){ // region 6
178 Tmp0 = A01 + B1;
179 Tmp1 = A00 + B0;
180 if (Tmp1 > Tmp0){
181 Numer = Tmp1 - Tmp0;
182 Denom = A00 - REAL(2.0) * A01 + A11;
183 if (Numer >= Denom){
184 v = REAL(1.0);
185 u = REAL(0.0);
186 DistSq = A11 + REAL(2.0) * B1 + C;
187 }
188 else{
189 v = Numer / Denom;
190 u = REAL(1.0) - v;
191 DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
192 }
193 }
194 else{
195 v = REAL(0.0);
196 if (Tmp1 <= REAL(0.0)){
197 u = REAL(1.0);
198 DistSq = A00 + REAL(2.0) * B0 + C;
199 }
200 else if(B0 >= REAL(0.0)){
201 u = REAL(0.0);
202 DistSq = C;
203 }
204 else{
205 u = -B0 / A00;
206 DistSq = B0 * u + C;
207 }
208 }
209 }
210 else{ // region 1
211 Numer = A11 + B1 - A01 - B0;
212 if (Numer <= REAL(0.0)){
213 u = REAL(0.0);
214 v = REAL(1.0);
215 DistSq = A11 + REAL(2.0) * B1 + C;
216 }
217 else{
218 Denom = A00 - REAL(2.0) * A01 + A11;
219 if (Numer >= Denom){
220 u = REAL(1.0);
221 v = REAL(0.0);
222 DistSq = A00 + REAL(2.0) * B0 + C;
223 }
224 else{
225 u = Numer / Denom;
226 v = REAL(1.0) - u;
227 DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
228 }
229 }
230 }
231 }
232
233 Dist = dSqrt(dFabs(DistSq));
234
235 if (Dist <= Radius){
236 Dist = Radius - Dist;
237 return true;
238 }
239 else return false;
240}
241
242int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride){
243 dIASSERT (Stride >= (int)sizeof(dContactGeom));
244 dIASSERT (g1->type == dTriMeshClass);
245 dIASSERT (SphereGeom->type == dSphereClass);
246 dIASSERT ((Flags & NUMC_MASK) >= 1);
247
248 dxTriMesh* TriMesh = (dxTriMesh*)g1;
249
250 // Init
251 const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh);
252 const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh);
253
254 SphereCollider& Collider = TriMesh->_SphereCollider;
255
256 const dVector3& Position = *(const dVector3*)dGeomGetPosition(SphereGeom);
257 dReal Radius = dGeomSphereGetRadius(SphereGeom);
258
259 // Sphere
260 Sphere Sphere;
261 Sphere.mCenter.x = Position[0];
262 Sphere.mCenter.y = Position[1];
263 Sphere.mCenter.z = Position[2];
264 Sphere.mRadius = Radius;
265
266 Matrix4x4 amatrix;
267
268 // TC results
269 if (TriMesh->doSphereTC) {
270 dxTriMesh::SphereTC* sphereTC = 0;
271 for (int i = 0; i < TriMesh->SphereTCCache.size(); i++){
272 if (TriMesh->SphereTCCache[i].Geom == SphereGeom){
273 sphereTC = &TriMesh->SphereTCCache[i];
274 break;
275 }
276 }
277
278 if (!sphereTC){
279 TriMesh->SphereTCCache.push(dxTriMesh::SphereTC());
280
281 sphereTC = &TriMesh->SphereTCCache[TriMesh->SphereTCCache.size() - 1];
282 sphereTC->Geom = SphereGeom;
283 }
284
285 // Intersect
286 Collider.SetTemporalCoherence(true);
287 Collider.Collide(*sphereTC, Sphere, TriMesh->Data->BVTree, null,
288 &MakeMatrix(TLPosition, TLRotation, amatrix));
289 }
290 else {
291 Collider.SetTemporalCoherence(false);
292 Collider.Collide(dxTriMesh::defaultSphereCache, Sphere, TriMesh->Data->BVTree, null,
293 &MakeMatrix(TLPosition, TLRotation, amatrix));
294 }
295
296 if (! Collider.GetContactStatus()) {
297 // no collision occurred
298 return 0;
299 }
300
301 // get results
302 int TriCount = Collider.GetNbTouchedPrimitives();
303 const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
304
305 if (TriCount != 0){
306 if (TriMesh->ArrayCallback != null){
307 TriMesh->ArrayCallback(TriMesh, SphereGeom, Triangles, TriCount);
308 }
309
310 int OutTriCount = 0;
311 for (int i = 0; i < TriCount; i++){
312 if (OutTriCount == (Flags & NUMC_MASK)){
313 break;
314 }
315
316 const int TriIndex = Triangles[i];
317
318 dVector3 dv[3];
319 if (!Callback(TriMesh, SphereGeom, TriIndex))
320 continue;
321 FetchTriangle(TriMesh, TriIndex, TLPosition, TLRotation, dv);
322
323 dVector3& v0 = dv[0];
324 dVector3& v1 = dv[1];
325 dVector3& v2 = dv[2];
326
327 dVector3 vu;
328 vu[0] = v1[0] - v0[0];
329 vu[1] = v1[1] - v0[1];
330 vu[2] = v1[2] - v0[2];
331 vu[3] = REAL(0.0);
332
333 dVector3 vv;
334 vv[0] = v2[0] - v0[0];
335 vv[1] = v2[1] - v0[1];
336 vv[2] = v2[2] - v0[2];
337 vv[3] = REAL(0.0);
338
339 // Get plane coefficients
340 dVector4 Plane;
341 dCROSS(Plane, =, vu, vv);
342
343 dReal Area = dSqrt(dDOT(Plane, Plane)); // We can use this later
344 Plane[0] /= Area;
345 Plane[1] /= Area;
346 Plane[2] /= Area;
347
348 Plane[3] = dDOT(Plane, v0);
349
350 /* If the center of the sphere is within the positive halfspace of the
351 * triangle's plane, allow a contact to be generated.
352 * If the center of the sphere made it into the positive halfspace of a
353 * back-facing triangle, then the physics update and/or velocity needs
354 * to be adjusted (penetration has occured anyway).
355 */
356
357 dReal side = dDOT(Plane,Position) - Plane[3];
358
359 if(side < REAL(0.0)) {
360 continue;
361 }
362
363 dReal Depth;
364 dReal u, v;
365 if (!GetContactData(Position, Radius, v0, vu, vv, Depth, u, v)){
366 continue; // Sphere doesn't hit triangle
367 }
368
369 if (Depth < REAL(0.0)){
370 Depth = REAL(0.0);
371 }
372
373 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride);
374
375 dReal w = REAL(1.0) - u - v;
376 Contact->pos[0] = (v0[0] * w) + (v1[0] * u) + (v2[0] * v);
377 Contact->pos[1] = (v0[1] * w) + (v1[1] * u) + (v2[1] * v);
378 Contact->pos[2] = (v0[2] * w) + (v1[2] * u) + (v2[2] * v);
379 Contact->pos[3] = REAL(0.0);
380
381 // Using normal as plane (reversed)
382 Contact->normal[0] = -Plane[0];
383 Contact->normal[1] = -Plane[1];
384 Contact->normal[2] = -Plane[2];
385 Contact->normal[3] = REAL(0.0);
386
387 // Depth returned from GetContactData is depth along
388 // contact point - sphere center direction
389 // we'll project it to contact normal
390 dVector3 dir;
391 dir[0] = Position[0]-Contact->pos[0];
392 dir[1] = Position[1]-Contact->pos[1];
393 dir[2] = Position[2]-Contact->pos[2];
394 dReal dirProj = dDOT(dir, Plane) / dSqrt(dDOT(dir, dir));
395 Contact->depth = Depth * dirProj;
396 //Contact->depth = Radius - side; // (mg) penetration depth is distance along normal not shortest distance
397 Contact->side1 = TriIndex;
398
399 //Contact->g1 = TriMesh;
400 //Contact->g2 = SphereGeom;
401
402 OutTriCount++;
403 }
404#ifdef MERGECONTACTS // Merge all contacts into 1
405 if (OutTriCount != 0){
406 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, 0, Stride);
407
408 if (OutTriCount != 1 && !(Flags & CONTACTS_UNIMPORTANT)){
409 Contact->normal[0] *= Contact->depth;
410 Contact->normal[1] *= Contact->depth;
411 Contact->normal[2] *= Contact->depth;
412 Contact->normal[3] *= Contact->depth;
413
414 for (int i = 1; i < OutTriCount; i++){
415 dContactGeom* TempContact = SAFECONTACT(Flags, Contacts, i, Stride);
416
417 Contact->pos[0] += TempContact->pos[0];
418 Contact->pos[1] += TempContact->pos[1];
419 Contact->pos[2] += TempContact->pos[2];
420 Contact->pos[3] += TempContact->pos[3];
421
422 Contact->normal[0] += TempContact->normal[0] * TempContact->depth;
423 Contact->normal[1] += TempContact->normal[1] * TempContact->depth;
424 Contact->normal[2] += TempContact->normal[2] * TempContact->depth;
425 Contact->normal[3] += TempContact->normal[3] * TempContact->depth;
426 }
427
428 Contact->pos[0] /= OutTriCount;
429 Contact->pos[1] /= OutTriCount;
430 Contact->pos[2] /= OutTriCount;
431 Contact->pos[3] /= OutTriCount;
432
433 // Remember to divide in square space.
434 Contact->depth = dSqrt(dDOT(Contact->normal, Contact->normal) / OutTriCount);
435
436 dNormalize3(Contact->normal);
437 }
438
439 Contact->g1 = TriMesh;
440 Contact->g2 = SphereGeom;
441
442 // TODO:
443 // Side1 now contains index of triangle that gave first hit
444 // Probably we should find index of triangle with deepest penetration
445
446 return 1;
447 }
448 else return 0;
449#elif defined MERGECONTACTNORMALS // Merge all normals, and distribute between all contacts
450 if (OutTriCount != 0){
451 if (OutTriCount != 1 && !(Flags & CONTACTS_UNIMPORTANT)){
452 dVector3& Normal = SAFECONTACT(Flags, Contacts, 0, Stride)->normal;
453 Normal[0] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
454 Normal[1] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
455 Normal[2] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
456 Normal[3] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
457
458 for (int i = 1; i < OutTriCount; i++){
459 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
460
461 Normal[0] += Contact->normal[0] * Contact->depth;
462 Normal[1] += Contact->normal[1] * Contact->depth;
463 Normal[2] += Contact->normal[2] * Contact->depth;
464 Normal[3] += Contact->normal[3] * Contact->depth;
465 }
466 dNormalize3(Normal);
467
468 for (int i = 1; i < OutTriCount; i++){
469 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
470
471 Contact->normal[0] = Normal[0];
472 Contact->normal[1] = Normal[1];
473 Contact->normal[2] = Normal[2];
474 Contact->normal[3] = Normal[3];
475
476 Contact->g1 = TriMesh;
477 Contact->g2 = SphereGeom;
478 }
479 }
480 else{
481 SAFECONTACT(Flags, Contacts, 0, Stride)->g1 = TriMesh;
482 SAFECONTACT(Flags, Contacts, 0, Stride)->g2 = SphereGeom;
483 }
484
485 return OutTriCount;
486 }
487 else return 0;
488#else //MERGECONTACTNORMALS // Just gather penetration depths and return
489 for (int i = 0; i < OutTriCount; i++){
490 dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
491
492 //Contact->depth = dSqrt(dDOT(Contact->normal, Contact->normal));
493
494 /*Contact->normal[0] /= Contact->depth;
495 Contact->normal[1] /= Contact->depth;
496 Contact->normal[2] /= Contact->depth;
497 Contact->normal[3] /= Contact->depth;*/
498
499 Contact->g1 = TriMesh;
500 Contact->g2 = SphereGeom;
501 }
502
503 return OutTriCount;
504#endif // MERGECONTACTS
505 }
506 else return 0;
507}
508#endif // dTRIMESH_OPCODE
509
510#if dTRIMESH_GIMPACT
511int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride)
512{
513 dIASSERT (Stride >= (int)sizeof(dContactGeom));
514 dIASSERT (g1->type == dTriMeshClass);
515 dIASSERT (SphereGeom->type == dSphereClass);
516 dIASSERT ((Flags & NUMC_MASK) >= 1);
517
518 dxTriMesh* TriMesh = (dxTriMesh*)g1;
519 dVector3& Position = *(dVector3*)dGeomGetPosition(SphereGeom);
520 dReal Radius = dGeomSphereGetRadius(SphereGeom);
521 //Create contact list
522 GDYNAMIC_ARRAY trimeshcontacts;
523 GIM_CREATE_CONTACT_LIST(trimeshcontacts);
524
525 //Collide trimeshes
526 gim_trimesh_sphere_collision(&TriMesh->m_collision_trimesh,Position,Radius,&trimeshcontacts);
527
528 if(trimeshcontacts.m_size == 0)
529 {
530 GIM_DYNARRAY_DESTROY(trimeshcontacts);
531 return 0;
532 }
533
534 GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
535
536 unsigned contactcount = trimeshcontacts.m_size;
537 unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK);
538 if (contactcount > maxcontacts)
539 {
540 contactcount = maxcontacts;
541 }
542
543 dContactGeom* pcontact;
544 unsigned i;
545
546 for (i=0;i<contactcount;i++)
547 {
548 pcontact = SAFECONTACT(Flags, Contacts, i, Stride);
549
550 pcontact->pos[0] = ptrimeshcontacts->m_point[0];
551 pcontact->pos[1] = ptrimeshcontacts->m_point[1];
552 pcontact->pos[2] = ptrimeshcontacts->m_point[2];
553 pcontact->pos[3] = REAL(1.0);
554
555 pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
556 pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
557 pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
558 pcontact->normal[3] = 0;
559
560 pcontact->depth = ptrimeshcontacts->m_depth;
561 pcontact->g1 = g1;
562 pcontact->g2 = SphereGeom;
563
564 ptrimeshcontacts++;
565 }
566
567 GIM_DYNARRAY_DESTROY(trimeshcontacts);
568
569 return (int)contactcount;
570}
571#endif // dTRIMESH_GIMPACT
572
573#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_trimesh.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_trimesh.cpp
deleted file mode 100644
index c9f209e..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_trimesh.cpp
+++ /dev/null
@@ -1,2033 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// OPCODE TriMesh/TriMesh collision code by Jeff Smith (c) 2004
24
25#ifdef _MSC_VER
26#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
27#endif
28
29#include <ode/collision.h>
30#include <ode/matrix.h>
31#include <ode/rotation.h>
32#include <ode/odemath.h>
33
34// Classic Implementation
35#if !dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER
36
37#if dTRIMESH_ENABLED
38
39#include "collision_util.h"
40#define TRIMESH_INTERNAL
41#include "collision_trimesh_internal.h"
42
43#if dTRIMESH_OPCODE
44
45#define SMALL_ELT REAL(2.5e-4)
46#define EXPANDED_ELT_THRESH REAL(1.0e-3)
47#define DISTANCE_EPSILON REAL(1.0e-8)
48#define VELOCITY_EPSILON REAL(1.0e-5)
49#define TINY_PENETRATION REAL(5.0e-6)
50
51struct LineContactSet
52{
53 enum
54 {
55 MAX_POINTS = 8
56 };
57
58 dVector3 Points[MAX_POINTS];
59 int Count;
60};
61
62
63static void GetTriangleGeometryCallback(udword, VertexPointers&, udword);
64static void GenerateContact(int, dContactGeom*, int, dxTriMesh*, dxTriMesh*,
65 const dVector3, const dVector3, dReal, int&);
66static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3],
67 dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar,
68 dReal isectpt1[3],dReal isectpt2[3]);
69inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B);
70static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv );
71static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3, dVector3);
72static bool FindTriSolidIntrsection(const dVector3 Tri[3],
73 const dVector4 Planes[6], int numSides,
74 LineContactSet& ClippedPolygon );
75static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& );
76static bool SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt,
77 dVector3 in_n, dVector3* in_col_v, dReal &out_depth);
78static int ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point);
79static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
80 const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
81 dReal *t,dReal *u,dReal *v);
82
83
84
85
86/* some math macros */
87#define CROSS(dest,v1,v2) { dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
88 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
89 dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; }
90
91#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
92
93#define SUB(dest,v1,v2) { dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2]; }
94
95#define ADD(dest,v1,v2) { dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2]; }
96
97#define MULT(dest,v,factor) { dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2]; }
98
99#define SET(dest,src) { dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2]; }
100
101#define SMULT(p,q,s) { p[0]=q[0]*s; p[1]=q[1]*s; p[2]=q[2]*s; }
102
103#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]; }
104
105#define LENGTH(x) ((dReal) dSqrt(dDOT(x, x)))
106
107#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];
108
109inline const dReal dMin(const dReal x, const dReal y)
110{
111 return x < y ? x : y;
112}
113
114
115inline void
116SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2,
117 dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2,
118 dVector3 n, dVector3 n1, dVector3 n2)
119{
120 if (pen_v == v1) {
121 pen_v = v2;
122 pen_elt = elt_f2;
123 col_v = v1;
124 SET(n, n1);
125 }
126 else {
127 pen_v = v1;
128 pen_elt = elt_f1;
129 col_v = v2;
130 SET(n, n2);
131 }
132}
133
134
135
136
137int
138dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
139{
140 dIASSERT (Stride >= (int)sizeof(dContactGeom));
141 dIASSERT (g1->type == dTriMeshClass);
142 dIASSERT (g2->type == dTriMeshClass);
143 dIASSERT ((Flags & NUMC_MASK) >= 1);
144
145 dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
146 dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
147
148 dReal * TriNormals1 = (dReal *) TriMesh1->Data->Normals;
149 dReal * TriNormals2 = (dReal *) TriMesh2->Data->Normals;
150
151 const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1);
152 // TLRotation1 = column-major order
153 const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1);
154
155 const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2);
156 // TLRotation2 = column-major order
157 const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2);
158
159 AABBTreeCollider& Collider = TriMesh1->_AABBTreeCollider;
160
161 static BVTCache ColCache;
162 ColCache.Model0 = &TriMesh1->Data->BVTree;
163 ColCache.Model1 = &TriMesh2->Data->BVTree;
164
165 // Collision query
166 Matrix4x4 amatrix, bmatrix;
167 BOOL IsOk = Collider.Collide(ColCache,
168 &MakeMatrix(TLPosition1, TLRotation1, amatrix),
169 &MakeMatrix(TLPosition2, TLRotation2, bmatrix) );
170
171
172 // Make "double" versions of these matrices, if appropriate
173 dMatrix4 A, B;
174 dMakeMatrix4(TLPosition1, TLRotation1, A);
175 dMakeMatrix4(TLPosition2, TLRotation2, B);
176
177
178 if (IsOk) {
179 // Get collision status => if true, objects overlap
180 if ( Collider.GetContactStatus() ) {
181 // Number of colliding pairs and list of pairs
182 int TriCount = Collider.GetNbPairs();
183 const Pair* CollidingPairs = Collider.GetPairs();
184
185 if (TriCount > 0) {
186 // step through the pairs, adding contacts
187 int id1, id2;
188 int OutTriCount = 0;
189 dVector3 v1[3], v2[3], CoplanarPt;
190 dVector3 e1, e2, e3, n1, n2, n, ContactNormal;
191 dReal depth;
192 dVector3 orig_pos, old_pos1, old_pos2, elt1, elt2, elt_sum;
193 dVector3 elt_f1[3], elt_f2[3];
194 dReal contact_elt_length = SMALL_ELT;
195 LineContactSet firstClippedTri, secondClippedTri;
196 dVector3 *firstClippedElt = new dVector3[LineContactSet::MAX_POINTS];
197 dVector3 *secondClippedElt = new dVector3[LineContactSet::MAX_POINTS];
198
199
200 // only do these expensive inversions once
201 dMatrix4 InvMatrix1, InvMatrix2;
202 dInvertMatrix4(A, InvMatrix1);
203 dInvertMatrix4(B, InvMatrix2);
204
205
206 for (int i = 0; i < TriCount; i++) {
207
208 id1 = CollidingPairs[i].id0;
209 id2 = CollidingPairs[i].id1;
210
211 // grab the colliding triangles
212 FetchTriangle((dxTriMesh*) g1, id1, TLPosition1, TLRotation1, v1);
213 FetchTriangle((dxTriMesh*) g2, id2, TLPosition2, TLRotation2, v2);
214 // Since we'll be doing matrix transfomrations, we need to
215 // make sure that all vertices have four elements
216 for (int j=0; j<3; j++) {
217 v1[j][3] = 1.0;
218 v2[j][3] = 1.0;
219 }
220
221
222 int IsCoplanar = 0;
223 dReal IsectPt1[3], IsectPt2[3];
224
225 // Sometimes OPCODE makes mistakes, so we look at the return
226 // value for TriTriIntersectWithIsectLine. A retcode of "0"
227 // means no intersection took place
228 if ( TriTriIntersectWithIsectLine( v1[0], v1[1], v1[2], v2[0], v2[1], v2[2],
229 &IsCoplanar,
230 IsectPt1, IsectPt2) ) {
231
232 // Compute the normals of the colliding faces
233 //
234 if (TriNormals1 == NULL) {
235 SUB( e1, v1[1], v1[0] );
236 SUB( e2, v1[2], v1[0] );
237 CROSS( n1, e1, e2 );
238 dNormalize3(n1);
239 }
240 else {
241 // If we were passed normals, we need to adjust them to take into
242 // account the objects' current rotations
243 e1[0] = TriNormals1[id1*3];
244 e1[1] = TriNormals1[id1*3 + 1];
245 e1[2] = TriNormals1[id1*3 + 2];
246 e1[3] = 0.0;
247
248 //dMultiply1(n1, TLRotation1, e1, 3, 3, 1);
249 dMultiply0(n1, TLRotation1, e1, 3, 3, 1);
250 n1[3] = 1.0;
251 }
252
253 if (TriNormals2 == NULL) {
254 SUB( e1, v2[1], v2[0] );
255 SUB( e2, v2[2], v2[0] );
256 CROSS( n2, e1, e2);
257 dNormalize3(n2);
258 }
259 else {
260 // If we were passed normals, we need to adjust them to take into
261 // account the objects' current rotations
262 e2[0] = TriNormals2[id2*3];
263 e2[1] = TriNormals2[id2*3 + 1];
264 e2[2] = TriNormals2[id2*3 + 2];
265 e2[3] = 0.0;
266
267 //dMultiply1(n2, TLRotation2, e2, 3, 3, 1);
268 dMultiply0(n2, TLRotation2, e2, 3, 3, 1);
269 n2[3] = 1.0;
270 }
271
272
273 if (IsCoplanar) {
274 // We can reach this case if the faces are coplanar, OR
275 // if they don't actually intersect. (OPCODE can make
276 // mistakes)
277 if (dFabs(dDOT(n1, n2)) > REAL(0.999)) {
278 // If the faces are coplanar, we declare that the point of
279 // contact is at the average location of the vertices of
280 // both faces
281 dVector3 ContactPt;
282 for (int j=0; j<3; j++) {
283 ContactPt[j] = 0.0;
284 for (int k=0; k<3; k++)
285 ContactPt[j] += v1[k][j] + v2[k][j];
286 ContactPt[j] /= 6.0;
287 }
288 ContactPt[3] = 1.0;
289
290 // and the contact normal is the normal of face 2
291 // (could be face 1, because they are the same)
292 SET(n, n2);
293
294 // and the penetration depth is the co-normal
295 // distance between any two vertices A and B,
296 // i.e. d = DOT(n, (A-B))
297 DEPTH(depth, v1[1], v2[1], n);
298 if (depth < 0)
299 depth *= -1.0;
300
301 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
302 ContactPt, n, depth, OutTriCount);
303 }
304 }
305 else {
306 // Otherwise (in non-co-planar cases), we create a coplanar
307 // point -- the middle of the line of intersection -- that
308 // will be used for various computations down the road
309 for (int j=0; j<3; j++)
310 CoplanarPt[j] = ( (IsectPt1[j] + IsectPt2[j]) / REAL(2.0) );
311 CoplanarPt[3] = 1.0;
312
313 // Find the ELT of the coplanar point
314 //
315 dMultiply1(orig_pos, InvMatrix1, CoplanarPt, 4, 4, 1);
316 dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
317 SUB(elt1, CoplanarPt, old_pos1);
318
319 dMultiply1(orig_pos, InvMatrix2, CoplanarPt, 4, 4, 1);
320 dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
321 SUB(elt2, CoplanarPt, old_pos2);
322
323 SUB(elt_sum, elt1, elt2); // net motion of the coplanar point
324
325
326 // Calculate how much the vertices of each face moved in the
327 // direction of the opposite face's normal
328 //
329 dReal total_dp1, total_dp2;
330 total_dp1 = 0.0;
331 total_dp2 = 0.0;
332
333 for (int ii=0; ii<3; ii++) {
334 // find the estimated linear translation (ELT) of the vertices
335 // on face 1, wrt to the center of face 2.
336
337 // un-transform this vertex by the current transform
338 dMultiply1(orig_pos, InvMatrix1, v1[ii], 4, 4, 1 );
339
340 // re-transform this vertex by last_trans (to get its old
341 // position)
342 dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
343
344 // Then subtract this position from our current one to find
345 // the elapsed linear translation (ELT)
346 for (int k=0; k<3; k++) {
347 elt_f1[ii][k] = (v1[ii][k] - old_pos1[k]) - elt2[k];
348 }
349
350 // Take the dot product of the ELT for each vertex (wrt the
351 // center of face2)
352 total_dp1 += dFabs( dDOT(elt_f1[ii], n2) );
353 }
354
355 for (int ii=0; ii<3; ii++) {
356 // find the estimated linear translation (ELT) of the vertices
357 // on face 2, wrt to the center of face 1.
358 dMultiply1(orig_pos, InvMatrix2, v2[ii], 4, 4, 1);
359 dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
360 for (int k=0; k<3; k++) {
361 elt_f2[ii][k] = (v2[ii][k] - old_pos2[k]) - elt1[k];
362 }
363
364 // Take the dot product of the ELT for each vertex (wrt the
365 // center of face2) and add them
366 total_dp2 += dFabs( dDOT(elt_f2[ii], n1) );
367 }
368
369
370 ////////
371 // Estimate the penetration depth.
372 //
373 dReal dp;
374 BOOL badPen = true;
375 dVector3 *pen_v; // the "penetrating vertices"
376 dVector3 *pen_elt; // the elt_f of the penetrating face
377 dVector3 *col_v; // the "collision vertices" (the penetrated face)
378
379 SMULT(n2, n2, -1.0); // SF PATCH #1335183
380 depth = 0.0;
381 if ((total_dp1 > DISTANCE_EPSILON) || (total_dp2 > DISTANCE_EPSILON)) {
382 ////////
383 // Find the collision normal, by finding the face
384 // that is pointed "most" in the direction of travel
385 // of the two triangles
386 //
387 if (total_dp2 > total_dp1) {
388 pen_v = v2;
389 pen_elt = elt_f2;
390 col_v = v1;
391 SET(n, n1);
392 }
393 else {
394 pen_v = v1;
395 pen_elt = elt_f1;
396 col_v = v2;
397 SET(n, n2);
398 }
399 }
400 else {
401 // the total_dp is very small, so let's fall back
402 // to a different test
403 if (LENGTH(elt2) > LENGTH(elt1)) {
404 pen_v = v2;
405 pen_elt = elt_f2;
406 col_v = v1;
407 SET(n, n1);
408 }
409 else {
410 pen_v = v1;
411 pen_elt = elt_f1;
412 col_v = v2;
413 SET(n, n2);
414 }
415 }
416
417
418 for (int j=0; j<3; j++)
419 if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) {
420 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
421 pen_v[j], n, depth, OutTriCount);
422 badPen = false;
423
424 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
425 break;
426 }
427 }
428
429
430 if (badPen) {
431 // try the other normal
432 SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
433
434 for (int j=0; j<3; j++)
435 if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) {
436 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
437 pen_v[j], n, depth, OutTriCount);
438 badPen = false;
439
440 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
441 break;
442 }
443 }
444 }
445
446
447
448 ////////////////////////////////////////
449 //
450 // If we haven't found a good penetration, then we're probably straddling
451 // the edge of one of the objects, or the penetraing face is big
452 // enough that all of its vertices are outside the bounds of the
453 // penetrated face.
454 // In these cases, we do a more expensive test. We clip the penetrating
455 // triangle with a solid defined by the penetrated triangle, and repeat
456 // the tests above on this new polygon
457 if (badPen) {
458
459 // Switch pen_v and n back again
460 SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
461
462
463 // Find the three sides (no top or bottom) of the solid defined by
464 // the edges of the penetrated triangle.
465
466 // The dVector4 "plane" structures contain the following information:
467 // [0]-[2]: The normal of the face, pointing INWARDS (i.e.
468 // the inverse normal
469 // [3]: The distance between the face and the center of the
470 // solid, along the normal
471 dVector4 SolidPlanes[3];
472 dVector3 tmp1;
473 dVector3 sn;
474
475 for (int j=0; j<3; j++) {
476 e1[j] = col_v[1][j] - col_v[0][j];
477 e2[j] = col_v[0][j] - col_v[2][j];
478 e3[j] = col_v[2][j] - col_v[1][j];
479 }
480
481 // side 1
482 CROSS(sn, e1, n);
483 dNormalize3(sn);
484 SMULT( SolidPlanes[0], sn, -1.0 );
485
486 ADD(tmp1, col_v[0], col_v[1]);
487 SMULT(tmp1, tmp1, 0.5); // center of edge
488 // distance from center to edge along normal
489 SolidPlanes[0][3] = dDOT(tmp1, SolidPlanes[0]);
490
491
492 // side 2
493 CROSS(sn, e2, n);
494 dNormalize3(sn);
495 SMULT( SolidPlanes[1], sn, -1.0 );
496
497 ADD(tmp1, col_v[0], col_v[2]);
498 SMULT(tmp1, tmp1, 0.5); // center of edge
499 // distance from center to edge along normal
500 SolidPlanes[1][3] = dDOT(tmp1, SolidPlanes[1]);
501
502
503 // side 3
504 CROSS(sn, e3, n);
505 dNormalize3(sn);
506 SMULT( SolidPlanes[2], sn, -1.0 );
507
508 ADD(tmp1, col_v[2], col_v[1]);
509 SMULT(tmp1, tmp1, 0.5); // center of edge
510 // distance from center to edge along normal
511 SolidPlanes[2][3] = dDOT(tmp1, SolidPlanes[2]);
512
513
514 FindTriSolidIntrsection(pen_v, SolidPlanes, 3, firstClippedTri);
515
516 for (int j=0; j<firstClippedTri.Count; j++) {
517 firstClippedTri.Points[j][3] = 1.0; // because we will be doing matrix mults
518
519 DEPTH(dp, CoplanarPt, firstClippedTri.Points[j], n);
520
521 // if the penetration depth (calculated above) is more than the contact
522 // point's ELT, then we've chosen the wrong face and should switch faces
523 if (pen_v == v1) {
524 dMultiply1(orig_pos, InvMatrix1, firstClippedTri.Points[j], 4, 4, 1);
525 dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
526 for (int k=0; k<3; k++) {
527 firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos1[k]) - elt2[k];
528 }
529 }
530 else {
531 dMultiply1(orig_pos, InvMatrix2, firstClippedTri.Points[j], 4, 4, 1);
532 dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
533 for (int k=0; k<3; k++) {
534 firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos2[k]) - elt1[k];
535 }
536 }
537
538 if (dp >= 0.0) {
539 contact_elt_length = dFabs(dDOT(firstClippedElt[j], n));
540
541 depth = dp;
542 if (depth == 0.0)
543 depth = dMin(DISTANCE_EPSILON, contact_elt_length);
544
545 if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
546 depth = contact_elt_length;
547
548 if (depth <= contact_elt_length) {
549 // Add a contact
550 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
551 firstClippedTri.Points[j], n, depth, OutTriCount);
552 badPen = false;
553
554 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
555 break;
556 }
557 }
558 }
559
560 }
561 }
562
563 if (badPen) {
564 // Switch pen_v and n (again!)
565 SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
566
567
568 // Find the three sides (no top or bottom) of the solid created by
569 // the penetrated triangle.
570 // The dVector4 "plane" structures contain the following information:
571 // [0]-[2]: The normal of the face, pointing INWARDS (i.e.
572 // the inverse normal
573 // [3]: The distance between the face and the center of the
574 // solid, along the normal
575 dVector4 SolidPlanes[3];
576 dVector3 tmp1;
577
578 dVector3 sn;
579 for (int j=0; j<3; j++) {
580 e1[j] = col_v[1][j] - col_v[0][j];
581 e2[j] = col_v[0][j] - col_v[2][j];
582 e3[j] = col_v[2][j] - col_v[1][j];
583 }
584
585 // side 1
586 CROSS(sn, e1, n);
587 dNormalize3(sn);
588 SMULT( SolidPlanes[0], sn, -1.0 );
589
590 ADD(tmp1, col_v[0], col_v[1]);
591 SMULT(tmp1, tmp1, 0.5); // center of edge
592 // distance from center to edge along normal
593 SolidPlanes[0][3] = dDOT(tmp1, SolidPlanes[0]);
594
595
596 // side 2
597 CROSS(sn, e2, n);
598 dNormalize3(sn);
599 SMULT( SolidPlanes[1], sn, -1.0 );
600
601 ADD(tmp1, col_v[0], col_v[2]);
602 SMULT(tmp1, tmp1, 0.5); // center of edge
603 // distance from center to edge along normal
604 SolidPlanes[1][3] = dDOT(tmp1, SolidPlanes[1]);
605
606
607 // side 3
608 CROSS(sn, e3, n);
609 dNormalize3(sn);
610 SMULT( SolidPlanes[2], sn, -1.0 );
611
612 ADD(tmp1, col_v[2], col_v[1]);
613 SMULT(tmp1, tmp1, 0.5); // center of edge
614 // distance from center to edge along normal
615 SolidPlanes[2][3] = dDOT(tmp1, SolidPlanes[2]);
616
617 FindTriSolidIntrsection(pen_v, SolidPlanes, 3, secondClippedTri);
618
619 for (int j=0; j<secondClippedTri.Count; j++) {
620 secondClippedTri.Points[j][3] = 1.0; // because we will be doing matrix mults
621
622 DEPTH(dp, CoplanarPt, secondClippedTri.Points[j], n);
623
624 if (pen_v == v1) {
625 dMultiply1(orig_pos, InvMatrix1, secondClippedTri.Points[j], 4, 4, 1);
626 dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
627 for (int k=0; k<3; k++) {
628 secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos1[k]) - elt2[k];
629 }
630 }
631 else {
632 dMultiply1(orig_pos, InvMatrix2, secondClippedTri.Points[j], 4, 4, 1);
633 dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
634 for (int k=0; k<3; k++) {
635 secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos2[k]) - elt1[k];
636 }
637 }
638
639
640 if (dp >= 0.0) {
641 contact_elt_length = dFabs(dDOT(secondClippedElt[j],n));
642
643 depth = dp;
644 if (depth == 0.0)
645 depth = dMin(DISTANCE_EPSILON, contact_elt_length);
646
647 if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
648 depth = contact_elt_length;
649
650 if (depth <= contact_elt_length) {
651 // Add a contact
652 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
653 secondClippedTri.Points[j], n, depth, OutTriCount);
654 badPen = false;
655
656 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
657 break;
658 }
659 }
660 }
661
662
663 }
664 }
665
666
667
668 /////////////////
669 // All conventional tests have failed at this point, so now we deal with
670 // cases on a more "heuristic" basis
671 //
672
673 if (badPen) {
674 // Switch pen_v and n (for the fourth time, so they're
675 // what my original guess said they were)
676 SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
677
678 if (dFabs(dDOT(n1, n2)) < REAL(0.01)) {
679 // If we reach this point, we have (close to) perpindicular
680 // faces, either resting on each other or sliding in a
681 // direction orthogonal to both surface normals.
682 if (LENGTH(elt_sum) < DISTANCE_EPSILON) {
683 depth = dFabs(dDOT(n, elt_sum));
684
685 if (depth > REAL(1e-12)) {
686 dNormalize3(n);
687 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
688 CoplanarPt, n, depth, OutTriCount);
689 badPen = false;
690 }
691 else {
692 // If the two faces are (nearly) perfectly at rest with
693 // respect to each other, then we ignore the contact,
694 // allowing the objects to slip a little in the hopes
695 // that next frame, they'll give us something to work
696 // with.
697 badPen = false;
698 }
699 }
700 else {
701 // The faces are perpindicular, but moving significantly
702 // This can be sliding, or an unusual edge-straddling
703 // penetration.
704 dVector3 cn;
705
706 CROSS(cn, n1, n2);
707 dNormalize3(cn);
708 SET(n, cn);
709
710 // The shallowest ineterpenetration of the faces
711 // is the depth
712 dVector3 ContactPt;
713 dVector3 dvTmp;
714 dReal rTmp;
715 depth = dInfinity;
716 for (int j=0; j<3; j++) {
717 for (int k=0; k<3; k++) {
718 SUB(dvTmp, col_v[k], pen_v[j]);
719
720 rTmp = dDOT(dvTmp, n);
721 if ( dFabs(rTmp) < dFabs(depth) ) {
722 depth = rTmp;
723 SET( ContactPt, pen_v[j] );
724 contact_elt_length = dFabs(dDOT(pen_elt[j], n));
725 }
726 }
727 }
728 if (depth < 0.0) {
729 SMULT(n, n, -1.0);
730 depth *= -1.0;
731 }
732
733 if ((depth > 0.0) && (depth <= contact_elt_length)) {
734 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
735 ContactPt, n, depth, OutTriCount);
736 badPen = false;
737 }
738
739 }
740 }
741 }
742
743
744 if (badPen) {
745 // Use as the normal the direction of travel, rather than any particular
746 // face normal
747 //
748 dVector3 esn;
749
750 if (pen_v == v1) {
751 SMULT(esn, elt_sum, -1.0);
752 }
753 else {
754 SET(esn, elt_sum);
755 }
756 dNormalize3(esn);
757
758
759 // The shallowest ineterpenetration of the faces
760 // is the depth
761 dVector3 ContactPt;
762 depth = dInfinity;
763 for (int j=0; j<3; j++) {
764 for (int k=0; k<3; k++) {
765 DEPTH(dp, col_v[k], pen_v[j], esn);
766 if ( (ExamineContactPoint(col_v, esn, pen_v[j])) &&
767 ( dFabs(dp) < dFabs(depth)) ) {
768 depth = dp;
769 SET( ContactPt, pen_v[j] );
770 contact_elt_length = dFabs(dDOT(pen_elt[j], esn));
771 }
772 }
773 }
774
775 if ((depth > 0.0) && (depth <= contact_elt_length)) {
776 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
777 ContactPt, esn, depth, OutTriCount);
778 badPen = false;
779 }
780 }
781
782
783 if (badPen) {
784 // If the direction of motion is perpindicular to both normals
785 if ( (dFabs(dDOT(n1, elt_sum)) < REAL(0.01)) && (dFabs(dDOT(n2, elt_sum)) < REAL(0.01)) ) {
786 dVector3 esn;
787 if (pen_v == v1) {
788 SMULT(esn, elt_sum, -1.0);
789 }
790 else {
791 SET(esn, elt_sum);
792 }
793
794 dNormalize3(esn);
795
796
797 // Look at the clipped points again, checking them against this
798 // new normal
799 for (int j=0; j<firstClippedTri.Count; j++) {
800 DEPTH(dp, CoplanarPt, firstClippedTri.Points[j], esn);
801
802 if (dp >= 0.0) {
803 contact_elt_length = dFabs(dDOT(firstClippedElt[j], esn));
804
805 depth = dp;
806 //if (depth == 0.0)
807 //depth = dMin(DISTANCE_EPSILON, contact_elt_length);
808
809 if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
810 depth = contact_elt_length;
811
812 if (depth <= contact_elt_length) {
813 // Add a contact
814 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
815 firstClippedTri.Points[j], esn, depth, OutTriCount);
816 badPen = false;
817
818 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
819 break;
820 }
821 }
822 }
823 }
824
825 if (badPen) {
826 // If this test failed, try it with the second set of clipped faces
827 for (int j=0; j<secondClippedTri.Count; j++) {
828 DEPTH(dp, CoplanarPt, secondClippedTri.Points[j], esn);
829
830 if (dp >= 0.0) {
831 contact_elt_length = dFabs(dDOT(secondClippedElt[j], esn));
832
833 depth = dp;
834 //if (depth == 0.0)
835 //depth = dMin(DISTANCE_EPSILON, contact_elt_length);
836
837 if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
838 depth = contact_elt_length;
839
840 if (depth <= contact_elt_length) {
841 // Add a contact
842 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
843 secondClippedTri.Points[j], esn, depth, OutTriCount);
844 badPen = false;
845
846 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
847 break;
848 }
849 }
850 }
851 }
852 }
853 }
854 }
855
856
857
858 if (badPen) {
859 // if we have very little motion, we're dealing with resting contact
860 // and shouldn't reference the ELTs at all
861 //
862 if (LENGTH(elt_sum) < VELOCITY_EPSILON) {
863
864 // instead of a "contact_elt_length" threshhold, we'll use an
865 // arbitrary, small one
866 for (int j=0; j<3; j++) {
867 DEPTH(dp, CoplanarPt, pen_v[j], n);
868
869 if (dp == 0.0)
870 dp = TINY_PENETRATION;
871
872 if ( (dp > 0.0) && (dp <= SMALL_ELT)) {
873 // Add a contact
874 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
875 pen_v[j], n, dp, OutTriCount);
876 badPen = false;
877
878 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
879 break;
880 }
881 }
882 }
883
884
885 if (badPen) {
886 // try the other normal
887 SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
888
889 for (int j=0; j<3; j++) {
890 DEPTH(dp, CoplanarPt, pen_v[j], n);
891
892 if (dp == 0.0)
893 dp = TINY_PENETRATION;
894
895 if ( (dp > 0.0) && (dp <= SMALL_ELT)) {
896 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
897 pen_v[j], n, dp, OutTriCount);
898 badPen = false;
899
900 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
901 break;
902 }
903 }
904 }
905 }
906
907
908
909 }
910 }
911
912 if (badPen) {
913 // find the nearest existing contact, and replicate it's
914 // normal and depth
915 //
916 dContactGeom* Contact;
917 dVector3 pos_diff;
918 dReal min_dist, dist;
919
920 min_dist = dInfinity;
921 depth = 0.0;
922 for (int j=0; j<OutTriCount; j++) {
923 Contact = SAFECONTACT(Flags, Contacts, j, Stride);
924
925 SUB(pos_diff, Contact->pos, CoplanarPt);
926
927 dist = dDOT(pos_diff, pos_diff);
928 if (dist < min_dist) {
929 min_dist = dist;
930 depth = Contact->depth;
931 SMULT(ContactNormal, Contact->normal, -1.0);
932 }
933 }
934
935 if (depth > 0.0) {
936 // Add a tiny contact at the coplanar point
937 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
938 CoplanarPt, ContactNormal, depth, OutTriCount);
939 badPen = false;
940 }
941 }
942
943
944 if (badPen) {
945 // Add a tiny contact at the coplanar point
946 if (-dDOT(elt_sum, n1) > -dDOT(elt_sum, n2)) {
947 SET(ContactNormal, n1);
948 }
949 else {
950 SET(ContactNormal, n2);
951 }
952
953 GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2,
954 CoplanarPt, ContactNormal, TINY_PENETRATION, OutTriCount);
955 badPen = false;
956 }
957
958
959 } // not coplanar (main loop)
960 } // TriTriIntersectWithIsectLine
961
962 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
963 break;
964 }
965 }
966
967 // Free memory
968 delete[] firstClippedElt;
969 delete[] secondClippedElt;
970
971 // Return the number of contacts
972 return OutTriCount;
973 }
974 }
975 }
976
977
978 // There was some kind of failure during the Collide call or
979 // there are no faces overlapping
980 return 0;
981}
982
983
984
985static void
986GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data)
987{
988 dVector3 Out[3];
989
990 FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out);
991
992 for (int i = 0; i < 3; i++)
993 triangle.Vertex[i] = (const Point*) ((dReal*) Out[i]);
994}
995
996
997//
998//
999//
1000#define B11 B[0]
1001#define B12 B[1]
1002#define B13 B[2]
1003#define B14 B[3]
1004#define B21 B[4]
1005#define B22 B[5]
1006#define B23 B[6]
1007#define B24 B[7]
1008#define B31 B[8]
1009#define B32 B[9]
1010#define B33 B[10]
1011#define B34 B[11]
1012#define B41 B[12]
1013#define B42 B[13]
1014#define B43 B[14]
1015#define B44 B[15]
1016
1017#define Binv11 Binv[0]
1018#define Binv12 Binv[1]
1019#define Binv13 Binv[2]
1020#define Binv14 Binv[3]
1021#define Binv21 Binv[4]
1022#define Binv22 Binv[5]
1023#define Binv23 Binv[6]
1024#define Binv24 Binv[7]
1025#define Binv31 Binv[8]
1026#define Binv32 Binv[9]
1027#define Binv33 Binv[10]
1028#define Binv34 Binv[11]
1029#define Binv41 Binv[12]
1030#define Binv42 Binv[13]
1031#define Binv43 Binv[14]
1032#define Binv44 Binv[15]
1033
1034inline void
1035dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B)
1036{
1037 B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2]; B41 = Position[0];
1038 B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6]; B42 = Position[1];
1039 B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10]; B43 = Position[2];
1040
1041 B14 = 0.0; B24 = 0.0; B34 = 0.0; B44 = 1.0;
1042}
1043
1044
1045static void
1046dInvertMatrix4( dMatrix4& B, dMatrix4& Binv )
1047{
1048 dReal det = (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43)
1049 -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42)
1050 +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42)
1051 +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41)
1052 -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41)
1053 +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41);
1054
1055 dAASSERT (det != 0.0);
1056
1057 det = 1.0 / det;
1058
1059 Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32)));
1060 Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12)));
1061 Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22)));
1062 Binv14 = 0.0f;
1063 Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33)));
1064 Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13)));
1065 Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23)));
1066 Binv24 = 0.0f;
1067 Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31)));
1068 Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11)));
1069 Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21)));
1070 Binv34 = 0.0f;
1071 Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42)));
1072 Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42)));
1073 Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22)));
1074 Binv44 = 1.0f;
1075}
1076
1077
1078
1079/////////////////////////////////////////////////
1080//
1081// Triangle/Triangle intersection utilities
1082//
1083// From the article "A Fast Triangle-Triangle Intersection Test",
1084// Journal of Graphics Tools, 2(2), 1997
1085//
1086// Some of this functionality is duplicated in OPCODE (see
1087// OPC_TriTriOverlap.h) but we have replicated it here so we don't
1088// have to mess with the internals of OPCODE, as well as so we can
1089// further optimize some of the functions.
1090//
1091// This version computes the line of intersection as well (if they
1092// are not coplanar):
1093// int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3],
1094// dReal U0[3],dReal U1[3],dReal U2[3],
1095// int *coplanar,
1096// dReal isectpt1[3],dReal isectpt2[3]);
1097//
1098// parameters: vertices of triangle 1: V0,V1,V2
1099// vertices of triangle 2: U0,U1,U2
1100//
1101// result : returns 1 if the triangles intersect, otherwise 0
1102// "coplanar" returns whether the tris are coplanar
1103// isectpt1, isectpt2 are the endpoints of the line of
1104// intersection
1105//
1106
1107
1108
1109/* if USE_EPSILON_TEST is true then we do a check:
1110 if |dv|<EPSILON then dv=0.0;
1111 else no check is done (which is less robust)
1112*/
1113#define USE_EPSILON_TEST TRUE
1114#define EPSILON REAL(0.000001)
1115
1116
1117/* sort so that a<=b */
1118#define SORT(a,b) \
1119 if(a>b) \
1120 { \
1121 dReal c; \
1122 c=a; \
1123 a=b; \
1124 b=c; \
1125 }
1126
1127#define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \
1128 isect0=VV0+(VV1-VV0)*D0/(D0-D1); \
1129 isect1=VV0+(VV2-VV0)*D0/(D0-D2);
1130
1131
1132#define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \
1133 if(D0D1>0.0f) \
1134 { \
1135 /* here we know that D0D2<=0.0 */ \
1136 /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
1137 ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
1138 } \
1139 else if(D0D2>0.0f) \
1140 { \
1141 /* here we know that d0d1<=0.0 */ \
1142 ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
1143 } \
1144 else if(D1*D2>0.0f || D0!=0.0f) \
1145 { \
1146 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
1147 ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1); \
1148 } \
1149 else if(D1!=0.0f) \
1150 { \
1151 ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
1152 } \
1153 else if(D2!=0.0f) \
1154 { \
1155 ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
1156 } \
1157 else \
1158 { \
1159 /* triangles are coplanar */ \
1160 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
1161 }
1162
1163
1164
1165/* this edge to edge test is based on Franlin Antonio's gem:
1166 "Faster Line Segment Intersection", in Graphics Gems III,
1167 pp. 199-202 */
1168#define EDGE_EDGE_TEST(V0,U0,U1) \
1169 Bx=U0[i0]-U1[i0]; \
1170 By=U0[i1]-U1[i1]; \
1171 Cx=V0[i0]-U0[i0]; \
1172 Cy=V0[i1]-U0[i1]; \
1173 f=Ay*Bx-Ax*By; \
1174 d=By*Cx-Bx*Cy; \
1175 if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
1176 { \
1177 e=Ax*Cy-Ay*Cx; \
1178 if(f>0) \
1179 { \
1180 if(e>=0 && e<=f) return 1; \
1181 } \
1182 else \
1183 { \
1184 if(e<=0 && e>=f) return 1; \
1185 } \
1186 }
1187
1188#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
1189{ \
1190 dReal Ax,Ay,Bx,By,Cx,Cy,e,d,f; \
1191 Ax=V1[i0]-V0[i0]; \
1192 Ay=V1[i1]-V0[i1]; \
1193 /* test edge U0,U1 against V0,V1 */ \
1194 EDGE_EDGE_TEST(V0,U0,U1); \
1195 /* test edge U1,U2 against V0,V1 */ \
1196 EDGE_EDGE_TEST(V0,U1,U2); \
1197 /* test edge U2,U1 against V0,V1 */ \
1198 EDGE_EDGE_TEST(V0,U2,U0); \
1199}
1200
1201#define POINT_IN_TRI(V0,U0,U1,U2) \
1202{ \
1203 dReal a,b,c,d0,d1,d2; \
1204 /* is T1 completly inside T2? */ \
1205 /* check if V0 is inside tri(U0,U1,U2) */ \
1206 a=U1[i1]-U0[i1]; \
1207 b=-(U1[i0]-U0[i0]); \
1208 c=-a*U0[i0]-b*U0[i1]; \
1209 d0=a*V0[i0]+b*V0[i1]+c; \
1210 \
1211 a=U2[i1]-U1[i1]; \
1212 b=-(U2[i0]-U1[i0]); \
1213 c=-a*U1[i0]-b*U1[i1]; \
1214 d1=a*V0[i0]+b*V0[i1]+c; \
1215 \
1216 a=U0[i1]-U2[i1]; \
1217 b=-(U0[i0]-U2[i0]); \
1218 c=-a*U2[i0]-b*U2[i1]; \
1219 d2=a*V0[i0]+b*V0[i1]+c; \
1220 if(d0*d1>0.0) \
1221 { \
1222 if(d0*d2>0.0) return 1; \
1223 } \
1224}
1225
1226int coplanar_tri_tri(dReal N[3],dReal V0[3],dReal V1[3],dReal V2[3],
1227 dReal U0[3],dReal U1[3],dReal U2[3])
1228{
1229 dReal A[3];
1230 short i0,i1;
1231 /* first project onto an axis-aligned plane, that maximizes the area */
1232 /* of the triangles, compute indices: i0,i1. */
1233 A[0]= dFabs(N[0]);
1234 A[1]= dFabs(N[1]);
1235 A[2]= dFabs(N[2]);
1236 if(A[0]>A[1])
1237 {
1238 if(A[0]>A[2])
1239 {
1240 i0=1; /* A[0] is greatest */
1241 i1=2;
1242 }
1243 else
1244 {
1245 i0=0; /* A[2] is greatest */
1246 i1=1;
1247 }
1248 }
1249 else /* A[0]<=A[1] */
1250 {
1251 if(A[2]>A[1])
1252 {
1253 i0=0; /* A[2] is greatest */
1254 i1=1;
1255 }
1256 else
1257 {
1258 i0=0; /* A[1] is greatest */
1259 i1=2;
1260 }
1261 }
1262
1263 /* test all edges of triangle 1 against the edges of triangle 2 */
1264 EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
1265 EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
1266 EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
1267
1268 /* finally, test if tri1 is totally contained in tri2 or vice versa */
1269 POINT_IN_TRI(V0,U0,U1,U2);
1270 POINT_IN_TRI(U0,V0,V1,V2);
1271
1272 return 0;
1273}
1274
1275
1276
1277#define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
1278{ \
1279 if(D0D1>0.0f) \
1280 { \
1281 /* here we know that D0D2<=0.0 */ \
1282 /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
1283 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
1284 } \
1285 else if(D0D2>0.0f)\
1286 { \
1287 /* here we know that d0d1<=0.0 */ \
1288 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
1289 } \
1290 else if(D1*D2>0.0f || D0!=0.0f) \
1291 { \
1292 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
1293 A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
1294 } \
1295 else if(D1!=0.0f) \
1296 { \
1297 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
1298 } \
1299 else if(D2!=0.0f) \
1300 { \
1301 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
1302 } \
1303 else \
1304 { \
1305 /* triangles are coplanar */ \
1306 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
1307 } \
1308}
1309
1310
1311
1312
1313/* sort so that a<=b */
1314#define SORT2(a,b,smallest) \
1315 if(a>b) \
1316 { \
1317 dReal c; \
1318 c=a; \
1319 a=b; \
1320 b=c; \
1321 smallest=1; \
1322 } \
1323 else smallest=0;
1324
1325
1326inline void isect2(dReal VTX0[3],dReal VTX1[3],dReal VTX2[3],dReal VV0,dReal VV1,dReal VV2,
1327 dReal D0,dReal D1,dReal D2,dReal *isect0,dReal *isect1,dReal isectpoint0[3],dReal isectpoint1[3])
1328{
1329 dReal tmp=D0/(D0-D1);
1330 dReal diff[3];
1331 *isect0=VV0+(VV1-VV0)*tmp;
1332 SUB(diff,VTX1,VTX0);
1333 MULT(diff,diff,tmp);
1334 ADD(isectpoint0,diff,VTX0);
1335 tmp=D0/(D0-D2);
1336 *isect1=VV0+(VV2-VV0)*tmp;
1337 SUB(diff,VTX2,VTX0);
1338 MULT(diff,diff,tmp);
1339 ADD(isectpoint1,VTX0,diff);
1340}
1341
1342
1343#if 0
1344#define ISECT2(VTX0,VTX1,VTX2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1) \
1345 tmp=D0/(D0-D1); \
1346 isect0=VV0+(VV1-VV0)*tmp; \
1347 SUB(diff,VTX1,VTX0); \
1348 MULT(diff,diff,tmp); \
1349 ADD(isectpoint0,diff,VTX0); \
1350 tmp=D0/(D0-D2);
1351/* isect1=VV0+(VV2-VV0)*tmp; \ */
1352/* SUB(diff,VTX2,VTX0); \ */
1353/* MULT(diff,diff,tmp); \ */
1354/* ADD(isectpoint1,VTX0,diff); */
1355#endif
1356
1357inline int compute_intervals_isectline(dReal VERT0[3],dReal VERT1[3],dReal VERT2[3],
1358 dReal VV0,dReal VV1,dReal VV2,dReal D0,dReal D1,dReal D2,
1359 dReal D0D1,dReal D0D2,dReal *isect0,dReal *isect1,
1360 dReal isectpoint0[3],dReal isectpoint1[3])
1361{
1362 if(D0D1>0.0f)
1363 {
1364 /* here we know that D0D2<=0.0 */
1365 /* that is D0, D1 are on the same side, D2 on the other or on the plane */
1366 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
1367 }
1368 else if(D0D2>0.0f)
1369 {
1370 /* here we know that d0d1<=0.0 */
1371 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
1372 }
1373 else if(D1*D2>0.0f || D0!=0.0f)
1374 {
1375 /* here we know that d0d1<=0.0 or that D0!=0.0 */
1376 isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1);
1377 }
1378 else if(D1!=0.0f)
1379 {
1380 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
1381 }
1382 else if(D2!=0.0f)
1383 {
1384 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
1385 }
1386 else
1387 {
1388 /* triangles are coplanar */
1389 return 1;
1390 }
1391 return 0;
1392}
1393
1394#define COMPUTE_INTERVALS_ISECTLINE(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1,isectpoint0,isectpoint1) \
1395 if(D0D1>0.0f) \
1396 { \
1397 /* here we know that D0D2<=0.0 */ \
1398 /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
1399 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \
1400 }
1401#if 0
1402 else if(D0D2>0.0f) \
1403 { \
1404 /* here we know that d0d1<=0.0 */ \
1405 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
1406 } \
1407 else if(D1*D2>0.0f || D0!=0.0f) \
1408 { \
1409 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
1410 isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
1411 } \
1412 else if(D1!=0.0f) \
1413 { \
1414 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
1415 } \
1416 else if(D2!=0.0f) \
1417 { \
1418 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \
1419 } \
1420 else \
1421 { \
1422 /* triangles are coplanar */ \
1423 coplanar=1; \
1424 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
1425 }
1426#endif
1427
1428
1429
1430static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3],
1431 dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar,
1432 dReal isectpt1[3],dReal isectpt2[3])
1433{
1434 dReal E1[3],E2[3];
1435 dReal N1[3],N2[3],d1,d2;
1436 dReal du0,du1,du2,dv0,dv1,dv2;
1437 dReal D[3];
1438 dReal isect1[2], isect2[2];
1439 dReal isectpointA1[3],isectpointA2[3];
1440 dReal isectpointB1[3],isectpointB2[3];
1441 dReal du0du1,du0du2,dv0dv1,dv0dv2;
1442 short index;
1443 dReal vp0,vp1,vp2;
1444 dReal up0,up1,up2;
1445 dReal b,c,max;
1446 int smallest1,smallest2;
1447
1448 /* compute plane equation of triangle(V0,V1,V2) */
1449 SUB(E1,V1,V0);
1450 SUB(E2,V2,V0);
1451 CROSS(N1,E1,E2);
1452 d1=-DOT(N1,V0);
1453 /* plane equation 1: N1.X+d1=0 */
1454
1455 /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/
1456 du0=DOT(N1,U0)+d1;
1457 du1=DOT(N1,U1)+d1;
1458 du2=DOT(N1,U2)+d1;
1459
1460 /* coplanarity robustness check */
1461#if USE_EPSILON_TEST==TRUE
1462 if(dFabs(du0)<EPSILON) du0=0.0;
1463 if(dFabs(du1)<EPSILON) du1=0.0;
1464 if(dFabs(du2)<EPSILON) du2=0.0;
1465#endif
1466 du0du1=du0*du1;
1467 du0du2=du0*du2;
1468
1469 if(du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */
1470 return 0; /* no intersection occurs */
1471
1472 /* compute plane of triangle (U0,U1,U2) */
1473 SUB(E1,U1,U0);
1474 SUB(E2,U2,U0);
1475 CROSS(N2,E1,E2);
1476 d2=-DOT(N2,U0);
1477 /* plane equation 2: N2.X+d2=0 */
1478
1479 /* put V0,V1,V2 into plane equation 2 */
1480 dv0=DOT(N2,V0)+d2;
1481 dv1=DOT(N2,V1)+d2;
1482 dv2=DOT(N2,V2)+d2;
1483
1484#if USE_EPSILON_TEST==TRUE
1485 if(dFabs(dv0)<EPSILON) dv0=0.0;
1486 if(dFabs(dv1)<EPSILON) dv1=0.0;
1487 if(dFabs(dv2)<EPSILON) dv2=0.0;
1488#endif
1489
1490 dv0dv1=dv0*dv1;
1491 dv0dv2=dv0*dv2;
1492
1493 if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
1494 return 0; /* no intersection occurs */
1495
1496 /* compute direction of intersection line */
1497 CROSS(D,N1,N2);
1498
1499 /* compute and index to the largest component of D */
1500 max= dFabs(D[0]);
1501 index=0;
1502 b= dFabs(D[1]);
1503 c= dFabs(D[2]);
1504 if(b>max) max=b,index=1;
1505 if(c>max) max=c,index=2;
1506
1507 /* this is the simplified projection onto L*/
1508 vp0=V0[index];
1509 vp1=V1[index];
1510 vp2=V2[index];
1511
1512 up0=U0[index];
1513 up1=U1[index];
1514 up2=U2[index];
1515
1516 /* compute interval for triangle 1 */
1517 *coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2,
1518 dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2);
1519 if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);
1520
1521
1522 /* compute interval for triangle 2 */
1523 compute_intervals_isectline(U0,U1,U2,up0,up1,up2,du0,du1,du2,
1524 du0du1,du0du2,&isect2[0],&isect2[1],isectpointB1,isectpointB2);
1525
1526 SORT2(isect1[0],isect1[1],smallest1);
1527 SORT2(isect2[0],isect2[1],smallest2);
1528
1529 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
1530
1531 /* at this point, we know that the triangles intersect */
1532
1533 if(isect2[0]<isect1[0])
1534 {
1535 if(smallest1==0) { SET(isectpt1,isectpointA1); }
1536 else { SET(isectpt1,isectpointA2); }
1537
1538 if(isect2[1]<isect1[1])
1539 {
1540 if(smallest2==0) { SET(isectpt2,isectpointB2); }
1541 else { SET(isectpt2,isectpointB1); }
1542 }
1543 else
1544 {
1545 if(smallest1==0) { SET(isectpt2,isectpointA2); }
1546 else { SET(isectpt2,isectpointA1); }
1547 }
1548 }
1549 else
1550 {
1551 if(smallest2==0) { SET(isectpt1,isectpointB1); }
1552 else { SET(isectpt1,isectpointB2); }
1553
1554 if(isect2[1]>isect1[1])
1555 {
1556 if(smallest1==0) { SET(isectpt2,isectpointA2); }
1557 else { SET(isectpt2,isectpointA1); }
1558 }
1559 else
1560 {
1561 if(smallest2==0) { SET(isectpt2,isectpointB2); }
1562 else { SET(isectpt2,isectpointB1); }
1563 }
1564 }
1565 return 1;
1566}
1567
1568
1569
1570
1571
1572// Find the intersectiojn point between a coplanar line segement,
1573// defined by X1 and X2, and a ray defined by X3 and direction N.
1574//
1575// This forumla for this calculation is:
1576// (c x b) . (a x b)
1577// Q = x1 + a -------------------
1578// | a x b | ^2
1579//
1580// where a = x2 - x1
1581// b = x4 - x3
1582// c = x3 - x1
1583// x1 and x2 are the edges of the triangle, and x3 is CoplanarPt
1584// and x4 is (CoplanarPt - n)
1585static int
1586IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n,
1587 dVector3 out_pt)
1588{
1589 dVector3 a, b, c, x4;
1590
1591 ADD(x4, x3, n); // x4 = x3 + n
1592
1593 SUB(a, x2, x1); // a = x2 - x1
1594 SUB(b, x4, x3);
1595 SUB(c, x3, x1);
1596
1597 dVector3 tmp1, tmp2;
1598 CROSS(tmp1, c, b);
1599 CROSS(tmp2, a, b);
1600
1601 dReal num, denom;
1602 num = dDOT(tmp1, tmp2);
1603 denom = LENGTH( tmp2 );
1604
1605 dReal s;
1606 s = num /(denom*denom);
1607
1608 for (int i=0; i<3; i++)
1609 out_pt[i] = x1[i] + a[i]*s;
1610
1611 // Test if this intersection is "behind" x3, w.r.t. n
1612 SUB(a, x3, out_pt);
1613 if (dDOT(a, n) > 0.0)
1614 return 0;
1615
1616 // Test if this intersection point is outside the edge limits,
1617 // if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside
1618 // else outside
1619 SUB(a, out_pt, x1);
1620 SUB(b, out_pt, x2);
1621 if (dDOT(a,b) < 0.0)
1622 return 1;
1623 else
1624 return 0;
1625}
1626
1627
1628// FindTriSolidIntersection - Clips the input trinagle TRI with the
1629// sides of a convex bounding solid, described by PLANES, returning
1630// the (convex) clipped polygon in CLIPPEDPOLYGON
1631//
1632static bool
1633FindTriSolidIntrsection(const dVector3 Tri[3],
1634 const dVector4 Planes[6], int numSides,
1635 LineContactSet& ClippedPolygon )
1636{
1637 // Set up the LineContactSet structure
1638 for (int k=0; k<3; k++) {
1639 SET(ClippedPolygon.Points[k], Tri[k]);
1640 }
1641 ClippedPolygon.Count = 3;
1642
1643 // Clip wrt the sides
1644 for ( int i = 0; i < numSides; i++ )
1645 ClipConvexPolygonAgainstPlane( Planes[i], Planes[i][3], ClippedPolygon );
1646
1647 return (ClippedPolygon.Count > 0);
1648}
1649
1650
1651
1652
1653// ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by
1654// CONTACTS, with a plane (described by N and C). Note: the input
1655// vertices are assumed to be in counterclockwise order.
1656//
1657// This code is taken from The Nebula Device:
1658// http://nebuladevice.sourceforge.net/cgi-bin/twiki/view/Nebula/WebHome
1659// and is licensed under the following license:
1660// http://nebuladevice.sourceforge.net/doc/source/license.txt
1661//
1662static void
1663ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C,
1664 LineContactSet& Contacts )
1665{
1666 // test on which side of line are the vertices
1667 int Positive = 0, Negative = 0, PIndex = -1;
1668 int Quantity = Contacts.Count;
1669
1670 dReal Test[8];
1671 for ( int i = 0; i < Contacts.Count; i++ ) {
1672 // An epsilon is used here because it is possible for the dot product
1673 // and C to be exactly equal to each other (in theory), but differ
1674 // slightly because of floating point problems. Thus, add a little
1675 // to the test number to push actually equal numbers over the edge
1676 // towards the positive. This should probably be somehow a relative
1677 // tolerance, and I don't think multiplying by the constant is the best
1678 // way to do this.
1679 Test[i] = dDOT(N, Contacts.Points[i]) - C + dFabs(C)*REAL(1e-08);
1680
1681 if (Test[i] >= REAL(0.0)) {
1682 Positive++;
1683 if (PIndex < 0) {
1684 PIndex = i;
1685 }
1686 }
1687 else Negative++;
1688 }
1689
1690 if (Positive > 0) {
1691 if (Negative > 0) {
1692 // plane transversely intersects polygon
1693 dVector3 CV[8];
1694 int CQuantity = 0, Cur, Prv;
1695 dReal T;
1696
1697 if (PIndex > 0) {
1698 // first clip vertex on line
1699 Cur = PIndex;
1700 Prv = Cur - 1;
1701 T = Test[Cur] / (Test[Cur] - Test[Prv]);
1702 CV[CQuantity][0] = Contacts.Points[Cur][0]
1703 + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
1704 CV[CQuantity][1] = Contacts.Points[Cur][1]
1705 + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
1706 CV[CQuantity][2] = Contacts.Points[Cur][2]
1707 + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
1708 CV[CQuantity][3] = Contacts.Points[Cur][3]
1709 + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
1710 CQuantity++;
1711
1712 // vertices on positive side of line
1713 while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
1714 CV[CQuantity][0] = Contacts.Points[Cur][0];
1715 CV[CQuantity][1] = Contacts.Points[Cur][1];
1716 CV[CQuantity][2] = Contacts.Points[Cur][2];
1717 CV[CQuantity][3] = Contacts.Points[Cur][3];
1718 CQuantity++;
1719 Cur++;
1720 }
1721
1722 // last clip vertex on line
1723 if (Cur < Quantity) {
1724 Prv = Cur - 1;
1725 }
1726 else {
1727 Cur = 0;
1728 Prv = Quantity - 1;
1729 }
1730
1731 T = Test[Cur] / (Test[Cur] - Test[Prv]);
1732 CV[CQuantity][0] = Contacts.Points[Cur][0]
1733 + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
1734 CV[CQuantity][1] = Contacts.Points[Cur][1]
1735 + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
1736 CV[CQuantity][2] = Contacts.Points[Cur][2]
1737 + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
1738 CV[CQuantity][3] = Contacts.Points[Cur][3]
1739 + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
1740 CQuantity++;
1741 }
1742 else {
1743 // iPIndex is 0
1744 // vertices on positive side of line
1745 Cur = 0;
1746 while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
1747 CV[CQuantity][0] = Contacts.Points[Cur][0];
1748 CV[CQuantity][1] = Contacts.Points[Cur][1];
1749 CV[CQuantity][2] = Contacts.Points[Cur][2];
1750 CV[CQuantity][3] = Contacts.Points[Cur][3];
1751 CQuantity++;
1752 Cur++;
1753 }
1754
1755 // last clip vertex on line
1756 Prv = Cur - 1;
1757 T = Test[Cur] / (Test[Cur] - Test[Prv]);
1758 CV[CQuantity][0] = Contacts.Points[Cur][0]
1759 + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
1760 CV[CQuantity][1] = Contacts.Points[Cur][1]
1761 + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
1762 CV[CQuantity][2] = Contacts.Points[Cur][2]
1763 + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
1764 CV[CQuantity][3] = Contacts.Points[Cur][3]
1765 + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
1766 CQuantity++;
1767
1768 // skip vertices on negative side
1769 while (Cur < Quantity && Test[Cur] < REAL(0.0)) {
1770 Cur++;
1771 }
1772
1773 // first clip vertex on line
1774 if (Cur < Quantity) {
1775 Prv = Cur - 1;
1776 T = Test[Cur] / (Test[Cur] - Test[Prv]);
1777 CV[CQuantity][0] = Contacts.Points[Cur][0]
1778 + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
1779 CV[CQuantity][1] = Contacts.Points[Cur][1]
1780 + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
1781 CV[CQuantity][2] = Contacts.Points[Cur][2]
1782 + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
1783 CV[CQuantity][3] = Contacts.Points[Cur][3]
1784 + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
1785 CQuantity++;
1786
1787 // vertices on positive side of line
1788 while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
1789 CV[CQuantity][0] = Contacts.Points[Cur][0];
1790 CV[CQuantity][1] = Contacts.Points[Cur][1];
1791 CV[CQuantity][2] = Contacts.Points[Cur][2];
1792 CV[CQuantity][3] = Contacts.Points[Cur][3];
1793 CQuantity++;
1794 Cur++;
1795 }
1796 }
1797 else {
1798 // iCur = 0
1799 Prv = Quantity - 1;
1800 T = Test[0] / (Test[0] - Test[Prv]);
1801 CV[CQuantity][0] = Contacts.Points[0][0]
1802 + T * (Contacts.Points[Prv][0] - Contacts.Points[0][0]);
1803 CV[CQuantity][1] = Contacts.Points[0][1]
1804 + T * (Contacts.Points[Prv][1] - Contacts.Points[0][1]);
1805 CV[CQuantity][2] = Contacts.Points[0][2]
1806 + T * (Contacts.Points[Prv][2] - Contacts.Points[0][2]);
1807 CV[CQuantity][3] = Contacts.Points[0][3]
1808 + T * (Contacts.Points[Prv][3] - Contacts.Points[0][3]);
1809 CQuantity++;
1810 }
1811 }
1812 Quantity = CQuantity;
1813 memcpy( Contacts.Points, CV, CQuantity * sizeof(dVector3) );
1814 }
1815 // else polygon fully on positive side of plane, nothing to do
1816 Contacts.Count = Quantity;
1817 }
1818 else {
1819 Contacts.Count = 0; // This should not happen, but for safety
1820 }
1821
1822}
1823
1824
1825
1826// Determine if a potential collision point is
1827//
1828//
1829static int
1830ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point)
1831{
1832 // Cast a ray from in_point, along the collison normal. Does it intersect the
1833 // collision face.
1834 dReal t, u, v;
1835
1836 if (!RayTriangleIntersect(in_point, in_n, v_col[0], v_col[1], v_col[2],
1837 &t, &u, &v))
1838 return 0;
1839 else
1840 return 1;
1841}
1842
1843
1844
1845// RayTriangleIntersect - If an intersection is found, t contains the
1846// distance along the ray (dir) and u/v contain u/v coordinates into
1847// the triangle. Returns 0 if no hit is found
1848// From "Real-Time Rendering," page 305
1849//
1850static int
1851RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
1852 const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
1853 dReal *t,dReal *u,dReal *v)
1854
1855{
1856 dReal edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
1857 dReal det,inv_det;
1858
1859 // find vectors for two edges sharing vert0
1860 SUB(edge1, vert1, vert0);
1861 SUB(edge2, vert2, vert0);
1862
1863 // begin calculating determinant - also used to calculate U parameter
1864 CROSS(pvec, dir, edge2);
1865
1866 // if determinant is near zero, ray lies in plane of triangle
1867 det = DOT(edge1, pvec);
1868
1869 if ((det > REAL(-0.001)) && (det < REAL(0.001)))
1870 return 0;
1871 inv_det = 1.0 / det;
1872
1873 // calculate distance from vert0 to ray origin
1874 SUB(tvec, orig, vert0);
1875
1876 // calculate U parameter and test bounds
1877 *u = DOT(tvec, pvec) * inv_det;
1878 if ((*u < 0.0) || (*u > 1.0))
1879 return 0;
1880
1881 // prepare to test V parameter
1882 CROSS(qvec, tvec, edge1);
1883
1884 // calculate V parameter and test bounds
1885 *v = DOT(dir, qvec) * inv_det;
1886 if ((*v < 0.0) || ((*u + *v) > 1.0))
1887 return 0;
1888
1889 // calculate t, ray intersects triangle
1890 *t = DOT(edge2, qvec) * inv_det;
1891
1892 return 1;
1893}
1894
1895
1896
1897static bool
1898SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt,
1899 dVector3 in_n, dVector3* in_col_v, dReal &out_depth)
1900{
1901 dReal dp = 0.0;
1902 dReal contact_elt_length;
1903
1904 DEPTH(dp, in_CoplanarPt, in_v, in_n);
1905
1906 if (dp >= 0.0) {
1907 // if the penetration depth (calculated above) is more than
1908 // the contact point's ELT, then we've chosen the wrong face
1909 // and should switch faces
1910 contact_elt_length = dFabs(dDOT(in_elt, in_n));
1911
1912 if (dp == 0.0)
1913 dp = dMin(DISTANCE_EPSILON, contact_elt_length);
1914
1915 if ((contact_elt_length < SMALL_ELT) && (dp < EXPANDED_ELT_THRESH))
1916 dp = contact_elt_length;
1917
1918 if ( (dp > 0.0) && (dp <= contact_elt_length)) {
1919 // Add a contact
1920
1921 if ( ExamineContactPoint(in_col_v, in_n, in_v) ) {
1922 out_depth = dp;
1923 return true;
1924 }
1925 }
1926 }
1927
1928 return false;
1929}
1930
1931
1932
1933
1934// Generate a "unique" contact. A unique contact has a unique
1935// position or normal. If the potential contact has the same
1936// position and normal as an existing contact, but a larger
1937// penetration depth, this new depth is used instead
1938//
1939static void
1940GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,
1941 dxTriMesh* in_TriMesh1, dxTriMesh* in_TriMesh2,
1942 const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
1943 int& OutTriCount)
1944{
1945 /*
1946 NOTE by Oleh_Derevenko:
1947 This function is called after maximal number of contacts has already been
1948 collected because it has a side effect of replacing penetration depth of
1949 existing contact with larger penetration depth of another matching normal contact.
1950 If this logic is not necessary any more, you can bail out on reach of contact
1951 number maximum immediately in dCollideTTL(). You will also need to correct
1952 conditional statements after invocations of GenerateContact() in dCollideTTL().
1953 */
1954 dIASSERT(in_Depth >= 0.0);
1955 //if (in_Depth < 0.0) -- the function is always called with depth >= 0
1956 // return;
1957
1958 do
1959 {
1960 dContactGeom* Contact;
1961 dVector3 diff;
1962
1963 if (!(in_Flags & CONTACTS_UNIMPORTANT))
1964 {
1965 bool duplicate = false;
1966
1967 for (int i=0; i<OutTriCount; i++)
1968 {
1969 Contact = SAFECONTACT(in_Flags, in_Contacts, i, in_Stride);
1970
1971 // same position?
1972 SUB(diff, in_ContactPos, Contact->pos);
1973 if (dDOT(diff, diff) < dEpsilon)
1974 {
1975 // same normal?
1976 if (dFabs(dDOT(in_Normal, Contact->normal)) > (REAL(1.0)-dEpsilon))
1977 {
1978 if (in_Depth > Contact->depth) {
1979 Contact->depth = in_Depth;
1980 SMULT( Contact->normal, in_Normal, -1.0);
1981 Contact->normal[3] = 0.0;
1982 }
1983 duplicate = true;
1984 /*
1985 NOTE by Oleh_Derevenko:
1986 There may be a case when two normals are close to each other but no duplicate
1987 while third normal is detected to be duplicate for both of them.
1988 This is the only reason I can think of, there is no "break" statement.
1989 Perhaps author considered it to be logical that the third normal would
1990 replace the depth in both of initial contacts.
1991 However, I consider it a questionable practice which should not
1992 be applied without deep understanding of underlaying physics.
1993 Even more, is this situation with close normal triplet acceptable at all?
1994 Should not be two initial contacts reduced to one (replaced with the latter)?
1995 If you know the answers for these questions, you may want to change this code.
1996 See the same statement in GenerateContact() of collision_trimesh_box.cpp
1997 */
1998 }
1999 }
2000 }
2001
2002 if (duplicate || OutTriCount == (in_Flags & NUMC_MASK))
2003 {
2004 break;
2005 }
2006 }
2007 else
2008 {
2009 dIASSERT(OutTriCount < (in_Flags & NUMC_MASK));
2010 }
2011
2012 // Add a new contact
2013 Contact = SAFECONTACT(in_Flags, in_Contacts, OutTriCount, in_Stride);
2014
2015 SET( Contact->pos, in_ContactPos );
2016 Contact->pos[3] = 0.0;
2017
2018 SMULT( Contact->normal, in_Normal, -1.0);
2019 Contact->normal[3] = 0.0;
2020
2021 Contact->depth = in_Depth;
2022
2023 Contact->g1 = in_TriMesh1;
2024 Contact->g2 = in_TriMesh2;
2025
2026 OutTriCount++;
2027 }
2028 while (false);
2029}
2030
2031#endif // dTRIMESH_OPCODE
2032#endif // !dTRIMESH_USE_NEW_TRIMESH_TRIMESH_COLLIDER
2033#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp b/libraries/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp
deleted file mode 100644
index c4af41c..0000000
--- a/libraries/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp
+++ /dev/null
@@ -1,1304 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// OPCODE TriMesh/TriMesh collision code
24// Written at 2006-10-28 by Francisco León (http://gimpact.sourceforge.net)
25
26#ifdef _MSC_VER
27#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
28#endif
29
30#include <ode/collision.h>
31#include <ode/matrix.h>
32#include <ode/rotation.h>
33#include <ode/odemath.h>
34
35// New Implementation
36#if dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER
37
38#if dTRIMESH_ENABLED
39
40#include "collision_util.h"
41#define TRIMESH_INTERNAL
42#include "collision_trimesh_internal.h"
43
44#if dTRIMESH_OPCODE
45
46#define SMALL_ELT REAL(2.5e-4)
47#define EXPANDED_ELT_THRESH REAL(1.0e-3)
48#define DISTANCE_EPSILON REAL(1.0e-8)
49#define VELOCITY_EPSILON REAL(1.0e-5)
50#define TINY_PENETRATION REAL(5.0e-6)
51
52struct LineContactSet
53{
54 enum
55 {
56 MAX_POINTS = 8
57 };
58
59 dVector3 Points[MAX_POINTS];
60 int Count;
61};
62
63
64static void GetTriangleGeometryCallback(udword, VertexPointers&, udword);
65inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B);
66static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv );
67static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3, dVector3);
68static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& );
69static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
70 const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
71 dReal *t,dReal *u,dReal *v);
72
73
74///returns the penetration depth
75static dReal MostDeepPoints(
76 LineContactSet & points,
77 const dVector3 plane_normal,
78 dReal plane_dist,
79 LineContactSet & deep_points);
80///returns the penetration depth
81static dReal FindMostDeepPointsInTetra(
82 LineContactSet contact_points,
83 const dVector3 sourcetri[3],///triangle which contains contact_points
84 const dVector3 tetra[4],
85 const dVector4 tetraplanes[4],
86 dVector3 separating_normal,
87 LineContactSet deep_points);
88
89static bool ClipTriByTetra(const dVector3 tri[3],
90 const dVector3 tetra[4],
91 LineContactSet& Contacts);
92static bool TriTriContacts(const dVector3 tr1[3],
93 const dVector3 tr2[3],
94 dxGeom* g1, dxGeom* g2, int Flags,
95 dContactGeom* Contacts, int Stride,
96 int &contactcount);
97
98
99/* some math macros */
100#define CROSS(dest,v1,v2) { dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
101 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
102 dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; }
103
104#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
105
106#define SUB(dest,v1,v2) { dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2]; }
107
108#define ADD(dest,v1,v2) { dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2]; }
109
110#define MULT(dest,v,factor) { dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2]; }
111
112#define SET(dest,src) { dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2]; }
113
114#define SMULT(p,q,s) { p[0]=q[0]*s; p[1]=q[1]*s; p[2]=q[2]*s; }
115
116#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]; }
117
118#define LENGTH(x) ((dReal) 1.0f/InvSqrt(dDOT(x, x)))
119
120#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];
121
122inline const dReal dMin(const dReal x, const dReal y)
123{
124 return x < y ? x : y;
125}
126
127
128inline void
129SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2,
130 dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2,
131 dVector3 n, dVector3 n1, dVector3 n2)
132{
133 if (pen_v == v1) {
134 pen_v = v2;
135 pen_elt = elt_f2;
136 col_v = v1;
137 SET(n, n1);
138 }
139 else {
140 pen_v = v1;
141 pen_elt = elt_f1;
142 col_v = v2;
143 SET(n, n2);
144 }
145}
146
147///////////////////////MECHANISM FOR AVOID CONTACT REDUNDANCE///////////////////////////////
148////* Written by Francisco León (http://gimpact.sourceforge.net) *///
149#define CONTACT_DIFF_EPSILON REAL(0.00001)
150#if defined(dDOUBLE)
151#define CONTACT_NORMAL_ZERO REAL(0.0000001)
152#else // if defined(dSINGLE)
153#define CONTACT_NORMAL_ZERO REAL(0.00001)
154#endif
155#define CONTACT_POS_HASH_QUOTIENT REAL(10000.0)
156#define dSQRT3 REAL(1.7320508075688773)
157
158struct CONTACT_KEY
159{
160 dContactGeom * m_contact;
161 unsigned int m_key;
162};
163
164#define MAXCONTACT_X_NODE 4
165struct CONTACT_KEY_HASH_NODE
166{
167 CONTACT_KEY m_keyarray[MAXCONTACT_X_NODE];
168 int m_keycount;
169};
170
171#define CONTACTS_HASHSIZE 256
172CONTACT_KEY_HASH_NODE g_hashcontactset[CONTACTS_HASHSIZE];
173
174
175
176void UpdateContactKey(CONTACT_KEY & key, dContactGeom * contact)
177{
178 key.m_contact = contact;
179
180 unsigned int hash=0;
181
182 int i = 0;
183
184 while (true)
185 {
186 dReal coord = contact->pos[i];
187 coord = dFloor(coord * CONTACT_POS_HASH_QUOTIENT);
188
189 unsigned int hash_input = ((unsigned int *)&coord)[0];
190 if (sizeof(dReal) / sizeof(unsigned int) != 1)
191 {
192 dIASSERT(sizeof(dReal) / sizeof(unsigned int) == 2);
193 hash_input ^= ((unsigned int *)&coord)[1];
194 }
195
196 hash = (( hash << 4 ) + (hash_input >> 24)) ^ ( hash >> 28 );
197 hash = (( hash << 4 ) + ((hash_input >> 16) & 0xFF)) ^ ( hash >> 28 );
198 hash = (( hash << 4 ) + ((hash_input >> 8) & 0xFF)) ^ ( hash >> 28 );
199 hash = (( hash << 4 ) + (hash_input & 0xFF)) ^ ( hash >> 28 );
200
201 if (++i == 3)
202 {
203 break;
204 }
205
206 hash = (hash << 11) | (hash >> 21);
207 }
208
209 key.m_key = hash;
210}
211
212
213static inline unsigned int MakeContactIndex(unsigned int key)
214{
215 dIASSERT(CONTACTS_HASHSIZE == 256);
216
217 unsigned int index = key ^ (key >> 16);
218 index = (index ^ (index >> 8)) & 0xFF;
219 return index;
220}
221
222dContactGeom *AddContactToNode(const CONTACT_KEY * contactkey,CONTACT_KEY_HASH_NODE * node)
223{
224 for(int i=0;i<node->m_keycount;i++)
225 {
226 if(node->m_keyarray[i].m_key == contactkey->m_key)
227 {
228 dContactGeom *contactfound = node->m_keyarray[i].m_contact;
229 if (dDISTANCE(contactfound->pos, contactkey->m_contact->pos) < REAL(1.00001) /*for comp. errors*/ * dSQRT3 / CONTACT_POS_HASH_QUOTIENT /*cube diagonal*/)
230 {
231 return contactfound;
232 }
233 }
234 }
235
236 if (node->m_keycount < MAXCONTACT_X_NODE)
237 {
238 node->m_keyarray[node->m_keycount].m_contact = contactkey->m_contact;
239 node->m_keyarray[node->m_keycount].m_key = contactkey->m_key;
240 node->m_keycount++;
241 }
242 else
243 {
244 dDEBUGMSG("Trimesh-trimesh contach hash table bucket overflow - close contacts might not be culled");
245 }
246
247 return contactkey->m_contact;
248}
249
250void RemoveNewContactFromNode(const CONTACT_KEY * contactkey, CONTACT_KEY_HASH_NODE * node)
251{
252 dIASSERT(node->m_keycount > 0);
253
254 if (node->m_keyarray[node->m_keycount - 1].m_contact == contactkey->m_contact)
255 {
256 node->m_keycount -= 1;
257 }
258 else
259 {
260 dIASSERT(node->m_keycount == MAXCONTACT_X_NODE);
261 }
262}
263
264void RemoveArbitraryContactFromNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node)
265{
266 dIASSERT(node->m_keycount > 0);
267
268 int keyindex, lastkeyindex = node->m_keycount - 1;
269
270 // Do not check the last contact
271 for (keyindex = 0; keyindex < lastkeyindex; keyindex++)
272 {
273 if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact)
274 {
275 node->m_keyarray[keyindex] = node->m_keyarray[lastkeyindex];
276 break;
277 }
278 }
279
280 dIASSERT(keyindex < lastkeyindex ||
281 node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match
282
283 node->m_keycount = lastkeyindex;
284}
285
286void UpdateArbitraryContactInNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node,
287 dContactGeom *pwithcontact)
288{
289 dIASSERT(node->m_keycount > 0);
290
291 int keyindex, lastkeyindex = node->m_keycount - 1;
292
293 // Do not check the last contact
294 for (keyindex = 0; keyindex < lastkeyindex; keyindex++)
295 {
296 if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact)
297 {
298 break;
299 }
300 }
301
302 dIASSERT(keyindex < lastkeyindex ||
303 node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match
304
305 node->m_keyarray[keyindex].m_contact = pwithcontact;
306}
307
308void ClearContactSet()
309{
310 memset(g_hashcontactset,0,sizeof(CONTACT_KEY_HASH_NODE)*CONTACTS_HASHSIZE);
311}
312
313//return true if found
314dContactGeom *InsertContactInSet(const CONTACT_KEY &newkey)
315{
316 unsigned int index = MakeContactIndex(newkey.m_key);
317
318 return AddContactToNode(&newkey, &g_hashcontactset[index]);
319}
320
321void RemoveNewContactFromSet(const CONTACT_KEY &contactkey)
322{
323 unsigned int index = MakeContactIndex(contactkey.m_key);
324
325 RemoveNewContactFromNode(&contactkey, &g_hashcontactset[index]);
326}
327
328void RemoveArbitraryContactFromSet(const CONTACT_KEY &contactkey)
329{
330 unsigned int index = MakeContactIndex(contactkey.m_key);
331
332 RemoveArbitraryContactFromNode(&contactkey, &g_hashcontactset[index]);
333}
334
335void UpdateArbitraryContactInSet(const CONTACT_KEY &contactkey,
336 dContactGeom *pwithcontact)
337{
338 unsigned int index = MakeContactIndex(contactkey.m_key);
339
340 UpdateArbitraryContactInNode(&contactkey, &g_hashcontactset[index], pwithcontact);
341}
342
343bool AllocNewContact(
344 const dVector3 newpoint, dContactGeom *& out_pcontact,
345 int Flags, dContactGeom* Contacts,
346 int Stride, int &contactcount)
347{
348 bool allocated_new = false;
349
350 dContactGeom dLocalContact;
351
352 dContactGeom * pcontact = contactcount != (Flags & NUMC_MASK) ?
353 SAFECONTACT(Flags, Contacts, contactcount, Stride) : &dLocalContact;
354
355 pcontact->pos[0] = newpoint[0];
356 pcontact->pos[1] = newpoint[1];
357 pcontact->pos[2] = newpoint[2];
358 pcontact->pos[3] = 1.0f;
359
360 CONTACT_KEY newkey;
361 UpdateContactKey(newkey, pcontact);
362
363 dContactGeom *pcontactfound = InsertContactInSet(newkey);
364 if (pcontactfound == pcontact)
365 {
366 if (pcontactfound != &dLocalContact)
367 {
368 contactcount++;
369 }
370 else
371 {
372 RemoveNewContactFromSet(newkey);
373 pcontactfound = NULL;
374 }
375
376 allocated_new = true;
377 }
378
379 out_pcontact = pcontactfound;
380 return allocated_new;
381}
382
383void FreeExistingContact(dContactGeom *pcontact,
384 int Flags, dContactGeom *Contacts,
385 int Stride, int &contactcount)
386{
387 CONTACT_KEY contactKey;
388 UpdateContactKey(contactKey, pcontact);
389
390 RemoveArbitraryContactFromSet(contactKey);
391
392 int lastContactIndex = contactcount - 1;
393 dContactGeom *plastContact = SAFECONTACT(Flags, Contacts, lastContactIndex, Stride);
394
395 if (pcontact != plastContact)
396 {
397 *pcontact = *plastContact;
398
399 CONTACT_KEY lastContactKey;
400 UpdateContactKey(lastContactKey, plastContact);
401
402 UpdateArbitraryContactInSet(lastContactKey, pcontact);
403 }
404
405 contactcount = lastContactIndex;
406}
407
408
409dContactGeom * PushNewContact( dxGeom* g1, dxGeom* g2,
410 const dVector3 point,
411 dVector3 normal,
412 dReal depth,
413 int Flags,
414 dContactGeom* Contacts, int Stride,
415 int &contactcount)
416{
417 dIASSERT(dFabs(dVector3Length((const dVector3 &)(*normal)) - REAL(1.0)) < REAL(1e-6)); // This assumption is used in the code
418
419 dContactGeom * pcontact;
420
421 if (!AllocNewContact(point, pcontact, Flags, Contacts, Stride, contactcount))
422 {
423 const dReal depthDifference = depth - pcontact->depth;
424
425 if (depthDifference > CONTACT_DIFF_EPSILON)
426 {
427 pcontact->normal[0] = normal[0];
428 pcontact->normal[1] = normal[1];
429 pcontact->normal[2] = normal[2];
430 pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging
431 pcontact->depth = depth;
432
433 pcontact->g1 = g1;
434 pcontact->g2 = g2;
435 }
436 else if (depthDifference >= -CONTACT_DIFF_EPSILON) ///average
437 {
438 if(pcontact->g1 == g2)
439 {
440 MULT(normal,normal, REAL(-1.0));
441 }
442
443 const dReal oldLen = pcontact->normal[3];
444 COMBO(pcontact->normal, normal, oldLen, pcontact->normal);
445
446 const dReal len = LENGTH(pcontact->normal);
447 if (len > CONTACT_NORMAL_ZERO)
448 {
449 MULT(pcontact->normal, pcontact->normal, REAL(1.0) / len);
450 pcontact->normal[3] = len;
451 }
452 else
453 {
454 FreeExistingContact(pcontact, Flags, Contacts, Stride, contactcount);
455 }
456 }
457 }
458 // Contact can be not available if buffer is full
459 else if (pcontact)
460 {
461 pcontact->normal[0] = normal[0];
462 pcontact->normal[1] = normal[1];
463 pcontact->normal[2] = normal[2];
464 pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging
465 pcontact->depth = depth;
466 pcontact->g1 = g1;
467 pcontact->g2 = g2;
468 }
469
470 return pcontact;
471}
472
473////////////////////////////////////////////////////////////////////////////////////////////
474
475
476
477
478
479int
480dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
481{
482 dIASSERT (Stride >= (int)sizeof(dContactGeom));
483 dIASSERT (g1->type == dTriMeshClass);
484 dIASSERT (g2->type == dTriMeshClass);
485 dIASSERT ((Flags & NUMC_MASK) >= 1);
486
487 dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
488 dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
489
490 dReal * TriNormals1 = (dReal *) TriMesh1->Data->Normals;
491 dReal * TriNormals2 = (dReal *) TriMesh2->Data->Normals;
492
493 const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1);
494 // TLRotation1 = column-major order
495 const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1);
496
497 const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2);
498 // TLRotation2 = column-major order
499 const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2);
500
501 AABBTreeCollider& Collider = TriMesh1->_AABBTreeCollider;
502
503
504 static BVTCache ColCache;
505 ColCache.Model0 = &TriMesh1->Data->BVTree;
506 ColCache.Model1 = &TriMesh2->Data->BVTree;
507
508 ////Prepare contact list
509 ClearContactSet();
510
511 // Collision query
512 Matrix4x4 amatrix, bmatrix;
513 BOOL IsOk = Collider.Collide(ColCache,
514 &MakeMatrix(TLPosition1, TLRotation1, amatrix),
515 &MakeMatrix(TLPosition2, TLRotation2, bmatrix) );
516
517
518 // Make "double" versions of these matrices, if appropriate
519 dMatrix4 A, B;
520 dMakeMatrix4(TLPosition1, TLRotation1, A);
521 dMakeMatrix4(TLPosition2, TLRotation2, B);
522
523
524
525
526 if (IsOk) {
527 // Get collision status => if true, objects overlap
528 if ( Collider.GetContactStatus() ) {
529 // Number of colliding pairs and list of pairs
530 int TriCount = Collider.GetNbPairs();
531 const Pair* CollidingPairs = Collider.GetPairs();
532
533 if (TriCount > 0) {
534 // step through the pairs, adding contacts
535 int id1, id2;
536 int OutTriCount = 0;
537 dVector3 v1[3], v2[3];
538
539 // only do these expensive inversions once
540 /*dMatrix4 InvMatrix1, InvMatrix2;
541 dInvertMatrix4(A, InvMatrix1);
542 dInvertMatrix4(B, InvMatrix2);*/
543
544
545 for (int i = 0; i < TriCount; i++)
546 {
547 id1 = CollidingPairs[i].id0;
548 id2 = CollidingPairs[i].id1;
549
550 // grab the colliding triangles
551 FetchTriangle((dxTriMesh*) g1, id1, TLPosition1, TLRotation1, v1);
552 FetchTriangle((dxTriMesh*) g2, id2, TLPosition2, TLRotation2, v2);
553 // Since we'll be doing matrix transformations, we need to
554 // make sure that all vertices have four elements
555 for (int j=0; j<3; j++) {
556 v1[j][3] = 1.0;
557 v2[j][3] = 1.0;
558 }
559
560 TriTriContacts(v1,v2,
561 g1, g2, Flags,
562 Contacts,Stride,OutTriCount);
563
564 // Continue loop even after contacts are full
565 // as existing contacts' normals/depths might be updated
566 // Break only if contacts are not important
567 if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
568 {
569 break;
570 }
571 }
572
573 // Return the number of contacts
574 return OutTriCount;
575
576 }
577 }
578 }
579
580
581 // There was some kind of failure during the Collide call or
582 // there are no faces overlapping
583 return 0;
584}
585
586
587
588static void
589GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data)
590{
591 dVector3 Out[3];
592
593 FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out);
594
595 for (int i = 0; i < 3; i++)
596 triangle.Vertex[i] = (const Point*) ((dReal*) Out[i]);
597}
598
599
600//
601//
602//
603#define B11 B[0]
604#define B12 B[1]
605#define B13 B[2]
606#define B14 B[3]
607#define B21 B[4]
608#define B22 B[5]
609#define B23 B[6]
610#define B24 B[7]
611#define B31 B[8]
612#define B32 B[9]
613#define B33 B[10]
614#define B34 B[11]
615#define B41 B[12]
616#define B42 B[13]
617#define B43 B[14]
618#define B44 B[15]
619
620#define Binv11 Binv[0]
621#define Binv12 Binv[1]
622#define Binv13 Binv[2]
623#define Binv14 Binv[3]
624#define Binv21 Binv[4]
625#define Binv22 Binv[5]
626#define Binv23 Binv[6]
627#define Binv24 Binv[7]
628#define Binv31 Binv[8]
629#define Binv32 Binv[9]
630#define Binv33 Binv[10]
631#define Binv34 Binv[11]
632#define Binv41 Binv[12]
633#define Binv42 Binv[13]
634#define Binv43 Binv[14]
635#define Binv44 Binv[15]
636
637inline void
638dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B)
639{
640 B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2]; B41 = Position[0];
641 B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6]; B42 = Position[1];
642 B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10]; B43 = Position[2];
643
644 B14 = 0.0; B24 = 0.0; B34 = 0.0; B44 = 1.0;
645}
646
647
648static void
649dInvertMatrix4( dMatrix4& B, dMatrix4& Binv )
650{
651 dReal det = (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43)
652 -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42)
653 +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42)
654 +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41)
655 -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41)
656 +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41);
657
658 dAASSERT (det != 0.0);
659
660 det = 1.0 / det;
661
662 Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32)));
663 Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12)));
664 Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22)));
665 Binv14 = 0.0f;
666 Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33)));
667 Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13)));
668 Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23)));
669 Binv24 = 0.0f;
670 Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31)));
671 Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11)));
672 Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21)));
673 Binv34 = 0.0f;
674 Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42)));
675 Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42)));
676 Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22)));
677 Binv44 = 1.0f;
678}
679
680
681
682// Find the intersectiojn point between a coplanar line segement,
683// defined by X1 and X2, and a ray defined by X3 and direction N.
684//
685// This forumla for this calculation is:
686// (c x b) . (a x b)
687// Q = x1 + a -------------------
688// | a x b | ^2
689//
690// where a = x2 - x1
691// b = x4 - x3
692// c = x3 - x1
693// x1 and x2 are the edges of the triangle, and x3 is CoplanarPt
694// and x4 is (CoplanarPt - n)
695static int
696IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n,
697 dVector3 out_pt)
698{
699 dVector3 a, b, c, x4;
700
701 ADD(x4, x3, n); // x4 = x3 + n
702
703 SUB(a, x2, x1); // a = x2 - x1
704 SUB(b, x4, x3);
705 SUB(c, x3, x1);
706
707 dVector3 tmp1, tmp2;
708 CROSS(tmp1, c, b);
709 CROSS(tmp2, a, b);
710
711 dReal num, denom;
712 num = dDOT(tmp1, tmp2);
713 denom = LENGTH( tmp2 );
714
715 dReal s;
716 s = num /(denom*denom);
717
718 for (int i=0; i<3; i++)
719 out_pt[i] = x1[i] + a[i]*s;
720
721 // Test if this intersection is "behind" x3, w.r.t. n
722 SUB(a, x3, out_pt);
723 if (dDOT(a, n) > 0.0)
724 return 0;
725
726 // Test if this intersection point is outside the edge limits,
727 // if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside
728 // else outside
729 SUB(a, out_pt, x1);
730 SUB(b, out_pt, x2);
731 if (dDOT(a,b) < 0.0)
732 return 1;
733 else
734 return 0;
735}
736
737
738
739void PlaneClipSegment( const dVector3 s1, const dVector3 s2,
740 const dVector3 N, dReal C, dVector3 clipped)
741{
742 dReal dis1,dis2;
743 dis1 = DOT(s1,N)-C;
744 SUB(clipped,s2,s1);
745 dis2 = DOT(clipped,N);
746 MULT(clipped,clipped,-dis1/dis2);
747 ADD(clipped,clipped,s1);
748 clipped[3] = 1.0f;
749}
750
751/* ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by
752 CONTACTS, with a plane (described by N and C distance from origin).
753 Note: the input vertices are assumed to be in invcounterclockwise order.
754 changed by Francisco Leon (http://gimpact.sourceforge.net) */
755static void
756ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C,
757 LineContactSet& Contacts )
758{
759 int i, vi, prevclassif=32000, classif;
760 /*
761 classif 0 : back, 1 : front
762 */
763
764 dReal d;
765 dVector3 clipped[8];
766 int clippedcount =0;
767
768 if(Contacts.Count==0)
769 {
770 return;
771 }
772 for(i=0;i<=Contacts.Count;i++)
773 {
774 vi = i%Contacts.Count;
775
776 d = DOT(N,Contacts.Points[vi]) - C;
777 ////classify point
778 if(d>REAL(1.0e-8)) classif = 1;
779 else classif = 0;
780
781 if(classif == 0)//back
782 {
783 if(i>0)
784 {
785 if(prevclassif==1)///in front
786 {
787
788 ///add clipped point
789 if(clippedcount<8)
790 {
791 PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi],
792 N,C,clipped[clippedcount]);
793 clippedcount++;
794 }
795 }
796 }
797 ///add point
798 if(clippedcount<8&&i<Contacts.Count)
799 {
800 clipped[clippedcount][0] = Contacts.Points[vi][0];
801 clipped[clippedcount][1] = Contacts.Points[vi][1];
802 clipped[clippedcount][2] = Contacts.Points[vi][2];
803 clipped[clippedcount][3] = 1.0f;
804 clippedcount++;
805 }
806 }
807 else
808 {
809
810 if(i>0)
811 {
812 if(prevclassif==0)
813 {
814 ///add point
815 if(clippedcount<8)
816 {
817 PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi],
818 N,C,clipped[clippedcount]);
819 clippedcount++;
820 }
821 }
822 }
823 }
824
825 prevclassif = classif;
826 }
827
828 if(clippedcount==0)
829 {
830 Contacts.Count = 0;
831 return;
832 }
833 Contacts.Count = clippedcount;
834 memcpy( Contacts.Points, clipped, clippedcount * sizeof(dVector3) );
835 return;
836}
837
838
839bool BuildPlane(const dVector3 s0, const dVector3 s1,const dVector3 s2,
840 dVector3 Normal, dReal & Dist)
841{
842 dVector3 e0,e1;
843 SUB(e0,s1,s0);
844 SUB(e1,s2,s0);
845
846 CROSS(Normal,e0,e1);
847
848 if (!dSafeNormalize3(Normal))
849 {
850 return false;
851 }
852
853 Dist = DOT(Normal,s0);
854 return true;
855
856}
857
858bool BuildEdgesDir(const dVector3 s0, const dVector3 s1,
859 const dVector3 t0, const dVector3 t1,
860 dVector3 crossdir)
861{
862 dVector3 e0,e1;
863
864 SUB(e0,s1,s0);
865 SUB(e1,t1,t0);
866 CROSS(crossdir,e0,e1);
867
868 if (!dSafeNormalize3(crossdir))
869 {
870 return false;
871 }
872 return true;
873}
874
875
876
877bool BuildEdgePlane(
878 const dVector3 s0, const dVector3 s1,
879 const dVector3 normal,
880 dVector3 plane_normal,
881 dReal & plane_dist)
882{
883 dVector3 e0;
884
885 SUB(e0,s1,s0);
886 CROSS(plane_normal,e0,normal);
887 if (!dSafeNormalize3(plane_normal))
888 {
889 return false;
890 }
891 plane_dist = DOT(plane_normal,s0);
892 return true;
893}
894
895
896
897
898/*
899Positive penetration
900Negative number: they are separated
901*/
902dReal IntervalPenetration(dReal &vmin1,dReal &vmax1,
903 dReal &vmin2,dReal &vmax2)
904{
905 if(vmax1<=vmin2)
906 {
907 return -(vmin2-vmax1);
908 }
909 else
910 {
911 if(vmax2<=vmin1)
912 {
913 return -(vmin1-vmax2);
914 }
915 else
916 {
917 if(vmax1<=vmax2)
918 {
919 return vmax1-vmin2;
920 }
921
922 return vmax2-vmin1;
923 }
924
925 }
926 return 0;
927}
928
929void FindInterval(
930 const dVector3 * vertices, int verticecount,
931 dVector3 dir,dReal &vmin,dReal &vmax)
932{
933
934 dReal dist;
935 int i;
936 vmin = DOT(vertices[0],dir);
937 vmax = vmin;
938 for(i=1;i<verticecount;i++)
939 {
940 dist = DOT(vertices[i],dir);
941 if(vmin>dist) vmin=dist;
942 else if(vmax<dist) vmax=dist;
943 }
944}
945
946///returns the penetration depth
947dReal MostDeepPoints(
948 LineContactSet & points,
949 const dVector3 plane_normal,
950 dReal plane_dist,
951 LineContactSet & deep_points)
952{
953 int i;
954 int max_candidates[8];
955 dReal maxdeep=-dInfinity;
956 dReal dist;
957
958 deep_points.Count = 0;
959 for(i=0;i<points.Count;i++)
960 {
961 dist = DOT(plane_normal,points.Points[i]) - plane_dist;
962 dist *= -1.0f;
963 if(dist>maxdeep)
964 {
965 maxdeep = dist;
966 deep_points.Count=1;
967 max_candidates[deep_points.Count-1] = i;
968 }
969 else if(dist+REAL(0.000001)>=maxdeep)
970 {
971 deep_points.Count++;
972 max_candidates[deep_points.Count-1] = i;
973 }
974 }
975
976 for(i=0;i<deep_points.Count;i++)
977 {
978 SET(deep_points.Points[i],points.Points[max_candidates[i]]);
979 }
980 return maxdeep;
981
982}
983
984void ClipPointsByTri(
985 const dVector3 * points, int pointcount,
986 const dVector3 tri[3],
987 const dVector3 triplanenormal,
988 dReal triplanedist,
989 LineContactSet & clipped_points,
990 bool triplane_clips)
991{
992 ///build edges planes
993 int i;
994 dVector4 plane;
995
996 clipped_points.Count = pointcount;
997 memcpy(&clipped_points.Points[0],&points[0],pointcount*sizeof(dVector3));
998 for(i=0;i<3;i++)
999 {
1000 if (BuildEdgePlane(
1001 tri[i],tri[(i+1)%3],triplanenormal,
1002 plane,plane[3]))
1003 {
1004 ClipConvexPolygonAgainstPlane(
1005 plane,
1006 plane[3],
1007 clipped_points);
1008 }
1009 }
1010
1011 if(triplane_clips)
1012 {
1013 ClipConvexPolygonAgainstPlane(
1014 triplanenormal,
1015 triplanedist,
1016 clipped_points);
1017 }
1018}
1019
1020
1021///returns the penetration depth
1022dReal FindTriangleTriangleCollision(
1023 const dVector3 tri1[3],
1024 const dVector3 tri2[3],
1025 dVector3 separating_normal,
1026 LineContactSet & deep_points)
1027{
1028 dReal maxdeep=dInfinity;
1029 dReal dist;
1030 int mostdir=0,mostface = 0, currdir=0;
1031// dReal vmin1,vmax1,vmin2,vmax2;
1032// dVector3 crossdir, pt1,pt2;
1033 dVector4 tri1plane,tri2plane;
1034 separating_normal[3] = 0.0f;
1035 bool bl;
1036 LineContactSet clipped_points1,clipped_points2;
1037 LineContactSet deep_points1,deep_points2;
1038 ////find interval face1
1039
1040 bl = BuildPlane(tri1[0],tri1[1],tri1[2],
1041 tri1plane,tri1plane[3]);
1042 clipped_points1.Count = 0;
1043
1044 if(bl)
1045 {
1046 ClipPointsByTri(
1047 tri2, 3,
1048 tri1,
1049 tri1plane,
1050 tri1plane[3],
1051 clipped_points1,false);
1052
1053
1054
1055 maxdeep = MostDeepPoints(
1056 clipped_points1,
1057 tri1plane,
1058 tri1plane[3],
1059 deep_points1);
1060 SET(separating_normal,tri1plane);
1061
1062 }
1063 currdir++;
1064
1065 ////find interval face2
1066
1067 bl = BuildPlane(tri2[0],tri2[1],tri2[2],
1068 tri2plane,tri2plane[3]);
1069
1070
1071 clipped_points2.Count = 0;
1072 if(bl)
1073 {
1074 ClipPointsByTri(
1075 tri1, 3,
1076 tri2,
1077 tri2plane,
1078 tri2plane[3],
1079 clipped_points2,false);
1080
1081
1082
1083 dist = MostDeepPoints(
1084 clipped_points2,
1085 tri2plane,
1086 tri2plane[3],
1087 deep_points2);
1088
1089
1090
1091 if(dist<maxdeep)
1092 {
1093 maxdeep = dist;
1094 mostdir = currdir;
1095 mostface = 1;
1096 SET(separating_normal,tri2plane);
1097 }
1098 }
1099 currdir++;
1100
1101
1102 ///find edge edge distances
1103 ///test each edge plane
1104
1105 /*for(i=0;i<3;i++)
1106 {
1107
1108
1109 for(j=0;j<3;j++)
1110 {
1111
1112
1113 bl = BuildEdgesDir(
1114 tri1[i],tri1[(i+1)%3],
1115 tri2[j],tri2[(j+1)%3],
1116 crossdir);
1117
1118 ////find plane distance
1119
1120 if(bl)
1121 {
1122 FindInterval(tri1,3,crossdir,vmin1,vmax1);
1123 FindInterval(tri2,3,crossdir,vmin2,vmax2);
1124
1125 dist = IntervalPenetration(
1126 vmin1,
1127 vmax1,
1128 vmin2,
1129 vmax2);
1130 if(dist<maxdeep)
1131 {
1132 maxdeep = dist;
1133 mostdir = currdir;
1134 SET(separating_normal,crossdir);
1135 }
1136 }
1137 currdir++;
1138 }
1139 }*/
1140
1141
1142 ////check most dir for contacts
1143 if(mostdir==0)
1144 {
1145 ///find most deep points
1146 deep_points.Count = deep_points1.Count;
1147 memcpy(
1148 &deep_points.Points[0],
1149 &deep_points1.Points[0],
1150 deep_points1.Count*sizeof(dVector3));
1151
1152 ///invert normal for point to tri1
1153 MULT(separating_normal,separating_normal,-1.0f);
1154 }
1155 else if(mostdir==1)
1156 {
1157 deep_points.Count = deep_points2.Count;
1158 memcpy(
1159 &deep_points.Points[0],
1160 &deep_points2.Points[0],
1161 deep_points2.Count*sizeof(dVector3));
1162
1163 }
1164 /*else
1165 {///edge separation
1166 mostdir -= 2;
1167
1168 //edge 2
1169 j = mostdir%3;
1170 //edge 1
1171 i = mostdir/3;
1172
1173 ///find edge closest points
1174 dClosestLineSegmentPoints(
1175 tri1[i],tri1[(i+1)%3],
1176 tri2[j],tri2[(j+1)%3],
1177 pt1,pt2);
1178 ///find correct direction
1179
1180 SUB(crossdir,pt2,pt1);
1181
1182 vmin1 = LENGTH(crossdir);
1183 if(vmin1<REAL(0.000001))
1184 {
1185
1186 if(mostface==0)
1187 {
1188 vmin1 = DOT(separating_normal,tri1plane);
1189 if(vmin1>0.0)
1190 {
1191 MULT(separating_normal,separating_normal,-1.0f);
1192 deep_points.Count = 1;
1193 SET(deep_points.Points[0],pt2);
1194 }
1195 else
1196 {
1197 deep_points.Count = 1;
1198 SET(deep_points.Points[0],pt2);
1199 }
1200
1201 }
1202 else
1203 {
1204 vmin1 = DOT(separating_normal,tri2plane);
1205 if(vmin1<0.0)
1206 {
1207 MULT(separating_normal,separating_normal,-1.0f);
1208 deep_points.Count = 1;
1209 SET(deep_points.Points[0],pt2);
1210 }
1211 else
1212 {
1213 deep_points.Count = 1;
1214 SET(deep_points.Points[0],pt2);
1215 }
1216
1217 }
1218
1219
1220
1221
1222 }
1223 else
1224 {
1225 MULT(separating_normal,crossdir,1.0f/vmin1);
1226
1227 vmin1 = DOT(separating_normal,tri1plane);
1228 if(vmin1>0.0)
1229 {
1230 MULT(separating_normal,separating_normal,-1.0f);
1231 deep_points.Count = 1;
1232 SET(deep_points.Points[0],pt2);
1233 }
1234 else
1235 {
1236 deep_points.Count = 1;
1237 SET(deep_points.Points[0],pt2);
1238 }
1239
1240
1241 }
1242
1243
1244 }*/
1245 return maxdeep;
1246}
1247
1248
1249
1250///SUPPORT UP TO 8 CONTACTS
1251bool TriTriContacts(const dVector3 tr1[3],
1252 const dVector3 tr2[3],
1253 dxGeom* g1, dxGeom* g2, int Flags,
1254 dContactGeom* Contacts, int Stride,
1255 int &contactcount)
1256{
1257
1258
1259 dVector4 normal;
1260 dReal depth;
1261 ///Test Tri Vs Tri
1262// dContactGeom* pcontact;
1263 int ccount = 0;
1264 LineContactSet contactpoints;
1265 contactpoints.Count = 0;
1266
1267
1268
1269 ///find best direction
1270
1271 depth = FindTriangleTriangleCollision(
1272 tr1,
1273 tr2,
1274 normal,
1275 contactpoints);
1276
1277
1278
1279 if(depth<0.0f) return false;
1280
1281 ccount = 0;
1282 while (ccount<contactpoints.Count)
1283 {
1284 PushNewContact( g1, g2,
1285 contactpoints.Points[ccount],
1286 normal, depth, Flags,
1287 Contacts,Stride,contactcount);
1288
1289 // Continue loop even after contacts are full
1290 // as existing contacts' normals/depths might be updated
1291 // Break only if contacts are not important
1292 if ((contactcount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
1293 {
1294 break;
1295 }
1296
1297 ccount++;
1298 }
1299 return true;
1300}
1301
1302#endif // dTRIMESH_OPCODE
1303#endif // dTRIMESH_USE_NEW_TRIMESH_TRIMESH_COLLIDER
1304#endif // dTRIMESH_ENABLED
diff --git a/libraries/ode-0.9/ode/src/collision_util.cpp b/libraries/ode-0.9/ode/src/collision_util.cpp
deleted file mode 100644
index 460cc20..0000000
--- a/libraries/ode-0.9/ode/src/collision_util.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25some useful collision utility stuff. this includes some API utility
26functions that are defined in the public header files.
27
28*/
29
30#include <ode/common.h>
31#include <ode/collision.h>
32#include <ode/odemath.h>
33#include "collision_util.h"
34
35//****************************************************************************
36
37int dCollideSpheres (dVector3 p1, dReal r1,
38 dVector3 p2, dReal r2, dContactGeom *c)
39{
40 // printf ("d=%.2f (%.2f %.2f %.2f) (%.2f %.2f %.2f) r1=%.2f r2=%.2f\n",
41 // d,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],r1,r2);
42
43 dReal d = dDISTANCE (p1,p2);
44 if (d > (r1 + r2)) return 0;
45 if (d <= 0) {
46 c->pos[0] = p1[0];
47 c->pos[1] = p1[1];
48 c->pos[2] = p1[2];
49 c->normal[0] = 1;
50 c->normal[1] = 0;
51 c->normal[2] = 0;
52 c->depth = r1 + r2;
53 }
54 else {
55 dReal d1 = dRecip (d);
56 c->normal[0] = (p1[0]-p2[0])*d1;
57 c->normal[1] = (p1[1]-p2[1])*d1;
58 c->normal[2] = (p1[2]-p2[2])*d1;
59 dReal k = REAL(0.5) * (r2 - r1 - d);
60 c->pos[0] = p1[0] + c->normal[0]*k;
61 c->pos[1] = p1[1] + c->normal[1]*k;
62 c->pos[2] = p1[2] + c->normal[2]*k;
63 c->depth = r1 + r2 - d;
64 }
65 return 1;
66}
67
68
69void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
70 const dVector3 pb, const dVector3 ub,
71 dReal *alpha, dReal *beta)
72{
73 dVector3 p;
74 p[0] = pb[0] - pa[0];
75 p[1] = pb[1] - pa[1];
76 p[2] = pb[2] - pa[2];
77 dReal uaub = dDOT(ua,ub);
78 dReal q1 = dDOT(ua,p);
79 dReal q2 = -dDOT(ub,p);
80 dReal d = 1-uaub*uaub;
81 if (d <= REAL(0.0001)) {
82 // @@@ this needs to be made more robust
83 *alpha = 0;
84 *beta = 0;
85 }
86 else {
87 d = dRecip(d);
88 *alpha = (q1 + uaub*q2)*d;
89 *beta = (uaub*q1 + q2)*d;
90 }
91}
92
93
94// given two line segments A and B with endpoints a1-a2 and b1-b2, return the
95// points on A and B that are closest to each other (in cp1 and cp2).
96// in the case of parallel lines where there are multiple solutions, a
97// solution involving the endpoint of at least one line will be returned.
98// this will work correctly for zero length lines, e.g. if a1==a2 and/or
99// b1==b2.
100//
101// the algorithm works by applying the voronoi clipping rule to the features
102// of the line segments. the three features of each line segment are the two
103// endpoints and the line between them. the voronoi clipping rule states that,
104// for feature X on line A and feature Y on line B, the closest points PA and
105// PB between X and Y are globally the closest points if PA is in V(Y) and
106// PB is in V(X), where V(X) is the voronoi region of X.
107
108void dClosestLineSegmentPoints (const dVector3 a1, const dVector3 a2,
109 const dVector3 b1, const dVector3 b2,
110 dVector3 cp1, dVector3 cp2)
111{
112 dVector3 a1a2,b1b2,a1b1,a1b2,a2b1,a2b2,n;
113 dReal la,lb,k,da1,da2,da3,da4,db1,db2,db3,db4,det;
114
115#define SET2(a,b) a[0]=b[0]; a[1]=b[1]; a[2]=b[2];
116#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];
117
118 // check vertex-vertex features
119
120 SET3 (a1a2,a2,-,a1);
121 SET3 (b1b2,b2,-,b1);
122 SET3 (a1b1,b1,-,a1);
123 da1 = dDOT(a1a2,a1b1);
124 db1 = dDOT(b1b2,a1b1);
125 if (da1 <= 0 && db1 >= 0) {
126 SET2 (cp1,a1);
127 SET2 (cp2,b1);
128 return;
129 }
130
131 SET3 (a1b2,b2,-,a1);
132 da2 = dDOT(a1a2,a1b2);
133 db2 = dDOT(b1b2,a1b2);
134 if (da2 <= 0 && db2 <= 0) {
135 SET2 (cp1,a1);
136 SET2 (cp2,b2);
137 return;
138 }
139
140 SET3 (a2b1,b1,-,a2);
141 da3 = dDOT(a1a2,a2b1);
142 db3 = dDOT(b1b2,a2b1);
143 if (da3 >= 0 && db3 >= 0) {
144 SET2 (cp1,a2);
145 SET2 (cp2,b1);
146 return;
147 }
148
149 SET3 (a2b2,b2,-,a2);
150 da4 = dDOT(a1a2,a2b2);
151 db4 = dDOT(b1b2,a2b2);
152 if (da4 >= 0 && db4 <= 0) {
153 SET2 (cp1,a2);
154 SET2 (cp2,b2);
155 return;
156 }
157
158 // check edge-vertex features.
159 // if one or both of the lines has zero length, we will never get to here,
160 // so we do not have to worry about the following divisions by zero.
161
162 la = dDOT(a1a2,a1a2);
163 if (da1 >= 0 && da3 <= 0) {
164 k = da1 / la;
165 SET3 (n,a1b1,-,k*a1a2);
166 if (dDOT(b1b2,n) >= 0) {
167 SET3 (cp1,a1,+,k*a1a2);
168 SET2 (cp2,b1);
169 return;
170 }
171 }
172
173 if (da2 >= 0 && da4 <= 0) {
174 k = da2 / la;
175 SET3 (n,a1b2,-,k*a1a2);
176 if (dDOT(b1b2,n) <= 0) {
177 SET3 (cp1,a1,+,k*a1a2);
178 SET2 (cp2,b2);
179 return;
180 }
181 }
182
183 lb = dDOT(b1b2,b1b2);
184 if (db1 <= 0 && db2 >= 0) {
185 k = -db1 / lb;
186 SET3 (n,-a1b1,-,k*b1b2);
187 if (dDOT(a1a2,n) >= 0) {
188 SET2 (cp1,a1);
189 SET3 (cp2,b1,+,k*b1b2);
190 return;
191 }
192 }
193
194 if (db3 <= 0 && db4 >= 0) {
195 k = -db3 / lb;
196 SET3 (n,-a2b1,-,k*b1b2);
197 if (dDOT(a1a2,n) <= 0) {
198 SET2 (cp1,a2);
199 SET3 (cp2,b1,+,k*b1b2);
200 return;
201 }
202 }
203
204 // it must be edge-edge
205
206 k = dDOT(a1a2,b1b2);
207 det = la*lb - k*k;
208 if (det <= 0) {
209 // this should never happen, but just in case...
210 SET2(cp1,a1);
211 SET2(cp2,b1);
212 return;
213 }
214 det = dRecip (det);
215 dReal alpha = (lb*da1 - k*db1) * det;
216 dReal beta = ( k*da1 - la*db1) * det;
217 SET3 (cp1,a1,+,alpha*a1a2);
218 SET3 (cp2,b1,+,beta*b1b2);
219
220# undef SET2
221# undef SET3
222}
223
224
225// a simple root finding algorithm is used to find the value of 't' that
226// satisfies:
227// d|D(t)|^2/dt = 0
228// where:
229// |D(t)| = |p(t)-b(t)|
230// where p(t) is a point on the line parameterized by t:
231// p(t) = p1 + t*(p2-p1)
232// and b(t) is that same point clipped to the boundary of the box. in box-
233// relative coordinates d|D(t)|^2/dt is the sum of three x,y,z components
234// each of which looks like this:
235//
236// t_lo /
237// ______/ -->t
238// / t_hi
239// /
240//
241// t_lo and t_hi are the t values where the line passes through the planes
242// corresponding to the sides of the box. the algorithm computes d|D(t)|^2/dt
243// in a piecewise fashion from t=0 to t=1, stopping at the point where
244// d|D(t)|^2/dt crosses from negative to positive.
245
246void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2,
247 const dVector3 c, const dMatrix3 R,
248 const dVector3 side,
249 dVector3 lret, dVector3 bret)
250{
251 int i;
252
253 // compute the start and delta of the line p1-p2 relative to the box.
254 // we will do all subsequent computations in this box-relative coordinate
255 // system. we have to do a translation and rotation for each point.
256 dVector3 tmp,s,v;
257 tmp[0] = p1[0] - c[0];
258 tmp[1] = p1[1] - c[1];
259 tmp[2] = p1[2] - c[2];
260 dMULTIPLY1_331 (s,R,tmp);
261 tmp[0] = p2[0] - p1[0];
262 tmp[1] = p2[1] - p1[1];
263 tmp[2] = p2[2] - p1[2];
264 dMULTIPLY1_331 (v,R,tmp);
265
266 // mirror the line so that v has all components >= 0
267 dVector3 sign;
268 for (i=0; i<3; i++) {
269 if (v[i] < 0) {
270 s[i] = -s[i];
271 v[i] = -v[i];
272 sign[i] = -1;
273 }
274 else sign[i] = 1;
275 }
276
277 // compute v^2
278 dVector3 v2;
279 v2[0] = v[0]*v[0];
280 v2[1] = v[1]*v[1];
281 v2[2] = v[2]*v[2];
282
283 // compute the half-sides of the box
284 dReal h[3];
285 h[0] = REAL(0.5) * side[0];
286 h[1] = REAL(0.5) * side[1];
287 h[2] = REAL(0.5) * side[2];
288
289 // region is -1,0,+1 depending on which side of the box planes each
290 // coordinate is on. tanchor is the next t value at which there is a
291 // transition, or the last one if there are no more.
292 int region[3];
293 dReal tanchor[3];
294
295 // Denormals are a problem, because we divide by v[i], and then
296 // multiply that by 0. Alas, infinity times 0 is infinity (!)
297 // We also use v2[i], which is v[i] squared. Here's how the epsilons
298 // are chosen:
299 // float epsilon = 1.175494e-038 (smallest non-denormal number)
300 // double epsilon = 2.225074e-308 (smallest non-denormal number)
301 // For single precision, choose an epsilon such that v[i] squared is
302 // not a denormal; this is for performance.
303 // For double precision, choose an epsilon such that v[i] is not a
304 // denormal; this is for correctness. (Jon Watte on mailinglist)
305
306#if defined( dSINGLE )
307 const dReal tanchor_eps = REAL(1e-19);
308#else
309 const dReal tanchor_eps = REAL(1e-307);
310#endif
311
312 // find the region and tanchor values for p1
313 for (i=0; i<3; i++) {
314 if (v[i] > tanchor_eps) {
315 if (s[i] < -h[i]) {
316 region[i] = -1;
317 tanchor[i] = (-h[i]-s[i])/v[i];
318 }
319 else {
320 region[i] = (s[i] > h[i]);
321 tanchor[i] = (h[i]-s[i])/v[i];
322 }
323 }
324 else {
325 region[i] = 0;
326 tanchor[i] = 2; // this will never be a valid tanchor
327 }
328 }
329
330 // compute d|d|^2/dt for t=0. if it's >= 0 then p1 is the closest point
331 dReal t=0;
332 dReal dd2dt = 0;
333 for (i=0; i<3; i++) dd2dt -= (region[i] ? v2[i] : 0) * tanchor[i];
334 if (dd2dt >= 0) goto got_answer;
335
336 do {
337 // find the point on the line that is at the next clip plane boundary
338 dReal next_t = 1;
339 for (i=0; i<3; i++) {
340 if (tanchor[i] > t && tanchor[i] < 1 && tanchor[i] < next_t)
341 next_t = tanchor[i];
342 }
343
344 // compute d|d|^2/dt for the next t
345 dReal next_dd2dt = 0;
346 for (i=0; i<3; i++) {
347 next_dd2dt += (region[i] ? v2[i] : 0) * (next_t - tanchor[i]);
348 }
349
350 // if the sign of d|d|^2/dt has changed, solution = the crossover point
351 if (next_dd2dt >= 0) {
352 dReal m = (next_dd2dt-dd2dt)/(next_t - t);
353 t -= dd2dt/m;
354 goto got_answer;
355 }
356
357 // advance to the next anchor point / region
358 for (i=0; i<3; i++) {
359 if (tanchor[i] == next_t) {
360 tanchor[i] = (h[i]-s[i])/v[i];
361 region[i]++;
362 }
363 }
364 t = next_t;
365 dd2dt = next_dd2dt;
366 }
367 while (t < 1);
368 t = 1;
369
370 got_answer:
371
372 // compute closest point on the line
373 for (i=0; i<3; i++) lret[i] = p1[i] + t*tmp[i]; // note: tmp=p2-p1
374
375 // compute closest point on the box
376 for (i=0; i<3; i++) {
377 tmp[i] = sign[i] * (s[i] + t*v[i]);
378 if (tmp[i] < -h[i]) tmp[i] = -h[i];
379 else if (tmp[i] > h[i]) tmp[i] = h[i];
380 }
381 dMULTIPLY0_331 (s,R,tmp);
382 for (i=0; i<3; i++) bret[i] = s[i] + c[i];
383}
384
385
386// given boxes (p1,R1,side1) and (p1,R1,side1), return 1 if they intersect
387// or 0 if not.
388
389int dBoxTouchesBox (const dVector3 p1, const dMatrix3 R1,
390 const dVector3 side1, const dVector3 p2,
391 const dMatrix3 R2, const dVector3 side2)
392{
393 // two boxes are disjoint if (and only if) there is a separating axis
394 // perpendicular to a face from one box or perpendicular to an edge from
395 // either box. the following tests are derived from:
396 // "OBB Tree: A Hierarchical Structure for Rapid Interference Detection",
397 // S.Gottschalk, M.C.Lin, D.Manocha., Proc of ACM Siggraph 1996.
398
399 // Rij is R1'*R2, i.e. the relative rotation between R1 and R2.
400 // Qij is abs(Rij)
401 dVector3 p,pp;
402 dReal A1,A2,A3,B1,B2,B3,R11,R12,R13,R21,R22,R23,R31,R32,R33,
403 Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33;
404
405 // get vector from centers of box 1 to box 2, relative to box 1
406 p[0] = p2[0] - p1[0];
407 p[1] = p2[1] - p1[1];
408 p[2] = p2[2] - p1[2];
409 dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
410
411 // get side lengths / 2
412 A1 = side1[0]*REAL(0.5); A2 = side1[1]*REAL(0.5); A3 = side1[2]*REAL(0.5);
413 B1 = side2[0]*REAL(0.5); B2 = side2[1]*REAL(0.5); B3 = side2[2]*REAL(0.5);
414
415 // for the following tests, excluding computation of Rij, in the worst case,
416 // 15 compares, 60 adds, 81 multiplies, and 24 absolutes.
417 // notation: R1=[u1 u2 u3], R2=[v1 v2 v3]
418
419 // separating axis = u1,u2,u3
420 R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
421 Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13);
422 if (dFabs(pp[0]) > (A1 + B1*Q11 + B2*Q12 + B3*Q13)) return 0;
423 R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
424 Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23);
425 if (dFabs(pp[1]) > (A2 + B1*Q21 + B2*Q22 + B3*Q23)) return 0;
426 R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
427 Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33);
428 if (dFabs(pp[2]) > (A3 + B1*Q31 + B2*Q32 + B3*Q33)) return 0;
429
430 // separating axis = v1,v2,v3
431 if (dFabs(dDOT41(R2+0,p)) > (A1*Q11 + A2*Q21 + A3*Q31 + B1)) return 0;
432 if (dFabs(dDOT41(R2+1,p)) > (A1*Q12 + A2*Q22 + A3*Q32 + B2)) return 0;
433 if (dFabs(dDOT41(R2+2,p)) > (A1*Q13 + A2*Q23 + A3*Q33 + B3)) return 0;
434
435 // separating axis = u1 x (v1,v2,v3)
436 if (dFabs(pp[2]*R21-pp[1]*R31) > A2*Q31 + A3*Q21 + B2*Q13 + B3*Q12) return 0;
437 if (dFabs(pp[2]*R22-pp[1]*R32) > A2*Q32 + A3*Q22 + B1*Q13 + B3*Q11) return 0;
438 if (dFabs(pp[2]*R23-pp[1]*R33) > A2*Q33 + A3*Q23 + B1*Q12 + B2*Q11) return 0;
439
440 // separating axis = u2 x (v1,v2,v3)
441 if (dFabs(pp[0]*R31-pp[2]*R11) > A1*Q31 + A3*Q11 + B2*Q23 + B3*Q22) return 0;
442 if (dFabs(pp[0]*R32-pp[2]*R12) > A1*Q32 + A3*Q12 + B1*Q23 + B3*Q21) return 0;
443 if (dFabs(pp[0]*R33-pp[2]*R13) > A1*Q33 + A3*Q13 + B1*Q22 + B2*Q21) return 0;
444
445 // separating axis = u3 x (v1,v2,v3)
446 if (dFabs(pp[1]*R11-pp[0]*R21) > A1*Q21 + A2*Q11 + B2*Q33 + B3*Q32) return 0;
447 if (dFabs(pp[1]*R12-pp[0]*R22) > A1*Q22 + A2*Q12 + B1*Q33 + B3*Q31) return 0;
448 if (dFabs(pp[1]*R13-pp[0]*R23) > A1*Q23 + A2*Q13 + B1*Q32 + B2*Q31) return 0;
449
450 return 1;
451}
452
453//****************************************************************************
454// other utility functions
455
456void dInfiniteAABB (dxGeom *geom, dReal aabb[6])
457{
458 aabb[0] = -dInfinity;
459 aabb[1] = dInfinity;
460 aabb[2] = -dInfinity;
461 aabb[3] = dInfinity;
462 aabb[4] = -dInfinity;
463 aabb[5] = dInfinity;
464}
465
466
467//****************************************************************************
468// Helpers for Croteam's collider - by Nguyen Binh
469
470int dClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane)
471{
472 // calculate distance of edge points to plane
473 dReal fDistance0 = dPointPlaneDistance( vEpnt0 ,plPlane );
474 dReal fDistance1 = dPointPlaneDistance( vEpnt1 ,plPlane );
475
476 // if both points are behind the plane
477 if ( fDistance0 < 0 && fDistance1 < 0 )
478 {
479 // do nothing
480 return 0;
481 // if both points in front of the plane
482 }
483 else if ( fDistance0 > 0 && fDistance1 > 0 )
484 {
485 // accept them
486 return 1;
487 // if we have edge/plane intersection
488 } else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0))
489 {
490
491 // find intersection point of edge and plane
492 dVector3 vIntersectionPoint;
493 vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1);
494 vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1);
495 vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1);
496
497 // clamp correct edge to intersection point
498 if ( fDistance0 < 0 )
499 {
500 dVector3Copy(vIntersectionPoint,vEpnt0);
501 } else
502 {
503 dVector3Copy(vIntersectionPoint,vEpnt1);
504 }
505 return 1;
506 }
507 return 1;
508}
509
510// clip polygon with plane and generate new polygon points
511void dClipPolyToPlane( const dVector3 avArrayIn[], const int ctIn,
512 dVector3 avArrayOut[], int &ctOut,
513 const dVector4 &plPlane )
514{
515 // start with no output points
516 ctOut = 0;
517
518 int i0 = ctIn-1;
519
520 // for each edge in input polygon
521 for (int i1=0; i1<ctIn; i0=i1, i1++) {
522
523
524 // calculate distance of edge points to plane
525 dReal fDistance0 = dPointPlaneDistance( avArrayIn[i0],plPlane );
526 dReal fDistance1 = dPointPlaneDistance( avArrayIn[i1],plPlane );
527
528 // if first point is in front of plane
529 if( fDistance0 >= 0 ) {
530 // emit point
531 avArrayOut[ctOut][0] = avArrayIn[i0][0];
532 avArrayOut[ctOut][1] = avArrayIn[i0][1];
533 avArrayOut[ctOut][2] = avArrayIn[i0][2];
534 ctOut++;
535 }
536
537 // if points are on different sides
538 if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) {
539
540 // find intersection point of edge and plane
541 dVector3 vIntersectionPoint;
542 vIntersectionPoint[0]= avArrayIn[i0][0] -
543 (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
544 vIntersectionPoint[1]= avArrayIn[i0][1] -
545 (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
546 vIntersectionPoint[2]= avArrayIn[i0][2] -
547 (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
548
549 // emit intersection point
550 avArrayOut[ctOut][0] = vIntersectionPoint[0];
551 avArrayOut[ctOut][1] = vIntersectionPoint[1];
552 avArrayOut[ctOut][2] = vIntersectionPoint[2];
553 ctOut++;
554 }
555 }
556
557}
558
559void dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn,
560 dVector3 avArrayOut[], int &ctOut,
561 const dVector4 &plPlane ,dReal fRadius)
562{
563 // start with no output points
564 ctOut = 0;
565
566 int i0 = ctIn-1;
567
568 // for each edge in input polygon
569 for (int i1=0; i1<ctIn; i0=i1, i1++)
570 {
571 // calculate distance of edge points to plane
572 dReal fDistance0 = dPointPlaneDistance( avArrayIn[i0],plPlane );
573 dReal fDistance1 = dPointPlaneDistance( avArrayIn[i1],plPlane );
574
575 // if first point is in front of plane
576 if( fDistance0 >= 0 )
577 {
578 // emit point
579 if (dVector3Length2(avArrayIn[i0]) <= fRadius*fRadius)
580 {
581 avArrayOut[ctOut][0] = avArrayIn[i0][0];
582 avArrayOut[ctOut][1] = avArrayIn[i0][1];
583 avArrayOut[ctOut][2] = avArrayIn[i0][2];
584 ctOut++;
585 }
586 }
587
588 // if points are on different sides
589 if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) )
590 {
591
592 // find intersection point of edge and plane
593 dVector3 vIntersectionPoint;
594 vIntersectionPoint[0]= avArrayIn[i0][0] -
595 (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
596 vIntersectionPoint[1]= avArrayIn[i0][1] -
597 (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
598 vIntersectionPoint[2]= avArrayIn[i0][2] -
599 (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
600
601 // emit intersection point
602 if (dVector3Length2(avArrayIn[i0]) <= fRadius*fRadius)
603 {
604 avArrayOut[ctOut][0] = vIntersectionPoint[0];
605 avArrayOut[ctOut][1] = vIntersectionPoint[1];
606 avArrayOut[ctOut][2] = vIntersectionPoint[2];
607 ctOut++;
608 }
609 }
610 }
611}
612
diff --git a/libraries/ode-0.9/ode/src/collision_util.h b/libraries/ode-0.9/ode/src/collision_util.h
deleted file mode 100644
index 4c479e3..0000000
--- a/libraries/ode-0.9/ode/src/collision_util.h
+++ /dev/null
@@ -1,340 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25some useful collision utility stuff.
26
27*/
28
29#ifndef _ODE_COLLISION_UTIL_H_
30#define _ODE_COLLISION_UTIL_H_
31
32#include <ode/common.h>
33#include <ode/contact.h>
34#include <ode/odemath.h>
35#include <ode/rotation.h>
36
37
38// given a pointer `p' to a dContactGeom, return the dContactGeom at
39// p + skip bytes.
40#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
41
42#if 1
43#include "collision_kernel.h"
44// Fetches a contact
45inline dContactGeom* SAFECONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){
46 dIASSERT(Index >= 0 && Index < (Flags & NUMC_MASK));
47 return ((dContactGeom*)(((char*)Contacts) + (Index * Stride)));
48}
49#endif
50
51
52// if the spheres (p1,r1) and (p2,r2) collide, set the contact `c' and
53// return 1, else return 0.
54
55int dCollideSpheres (dVector3 p1, dReal r1,
56 dVector3 p2, dReal r2, dContactGeom *c);
57
58
59// given two lines
60// qa = pa + alpha* ua
61// qb = pb + beta * ub
62// where pa,pb are two points, ua,ub are two unit length vectors, and alpha,
63// beta go from [-inf,inf], return alpha and beta such that qa and qb are
64// as close as possible
65
66void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
67 const dVector3 pb, const dVector3 ub,
68 dReal *alpha, dReal *beta);
69
70
71// given a line segment p1-p2 and a box (center 'c', rotation 'R', side length
72// vector 'side'), compute the points of closest approach between the box
73// and the line. return these points in 'lret' (the point on the line) and
74// 'bret' (the point on the box). if the line actually penetrates the box
75// then the solution is not unique, but only one solution will be returned.
76// in this case the solution points will coincide.
77
78void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2,
79 const dVector3 c, const dMatrix3 R,
80 const dVector3 side,
81 dVector3 lret, dVector3 bret);
82
83// 20 Apr 2004
84// Start code by Nguyen Binh
85int dClipEdgeToPlane(dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane);
86// clip polygon with plane and generate new polygon points
87void dClipPolyToPlane(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane );
88
89void dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ,dReal fRadius);
90
91// Some vector math
92inline void dVector3Subtract(const dVector3& a,const dVector3& b,dVector3& c)
93{
94 c[0] = a[0] - b[0];
95 c[1] = a[1] - b[1];
96 c[2] = a[2] - b[2];
97}
98
99// Some vector math
100inline void dVector3Scale(dVector3& a,dReal nScale)
101{
102 a[0] *= nScale ;
103 a[1] *= nScale ;
104 a[2] *= nScale ;
105}
106
107inline void dVector3Add(const dVector3& a,const dVector3& b,dVector3& c)
108{
109 c[0] = a[0] + b[0];
110 c[1] = a[1] + b[1];
111 c[2] = a[2] + b[2];
112}
113
114inline void dVector3Copy(const dVector3& a,dVector3& c)
115{
116 c[0] = a[0];
117 c[1] = a[1];
118 c[2] = a[2];
119}
120
121inline void dVector3Cross(const dVector3& a,const dVector3& b,dVector3& c)
122{
123 dCROSS(c,=,a,b);
124}
125
126inline dReal dVector3Length(const dVector3& a)
127{
128 return dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
129}
130
131inline dReal dVector3Dot(const dVector3& a,const dVector3& b)
132{
133 return dDOT(a,b);
134}
135
136inline void dVector3Inv(dVector3& a)
137{
138 a[0] = -a[0];
139 a[1] = -a[1];
140 a[2] = -a[2];
141}
142
143inline dReal dVector3Length2(const dVector3& a)
144{
145 return (a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
146}
147
148inline void dMat3GetCol(const dMatrix3& m,const int col, dVector3& v)
149{
150 v[0] = m[col + 0];
151 v[1] = m[col + 4];
152 v[2] = m[col + 8];
153}
154
155inline void dVector3CrossMat3Col(const dMatrix3& m,const int col,const dVector3& v,dVector3& r)
156{
157 r[0] = v[1] * m[2*4 + col] - v[2] * m[1*4 + col];
158 r[1] = v[2] * m[0*4 + col] - v[0] * m[2*4 + col];
159 r[2] = v[0] * m[1*4 + col] - v[1] * m[0*4 + col];
160}
161
162inline void dMat3ColCrossVector3(const dMatrix3& m,const int col,const dVector3& v,dVector3& r)
163{
164 r[0] = v[2] * m[1*4 + col] - v[1] * m[2*4 + col];
165 r[1] = v[0] * m[2*4 + col] - v[2] * m[0*4 + col];
166 r[2] = v[1] * m[0*4 + col] - v[0] * m[1*4 + col];
167}
168
169inline void dMultiplyMat3Vec3(const dMatrix3& m,const dVector3& v, dVector3& r)
170{
171 dMULTIPLY0_331(r,m,v);
172}
173
174inline dReal dPointPlaneDistance(const dVector3& point,const dVector4& plane)
175{
176 return (plane[0]*point[0] + plane[1]*point[1] + plane[2]*point[2] + plane[3]);
177}
178
179inline void dConstructPlane(const dVector3& normal,const dReal& distance, dVector4& plane)
180{
181 plane[0] = normal[0];
182 plane[1] = normal[1];
183 plane[2] = normal[2];
184 plane[3] = distance;
185}
186
187inline void dMatrix3Copy(const dReal* source,dMatrix3& dest)
188{
189 dest[0] = source[0];
190 dest[1] = source[1];
191 dest[2] = source[2];
192
193 dest[4] = source[4];
194 dest[5] = source[5];
195 dest[6] = source[6];
196
197 dest[8] = source[8];
198 dest[9] = source[9];
199 dest[10]= source[10];
200}
201
202inline dReal dMatrix3Det( const dMatrix3& mat )
203{
204 dReal det;
205
206 det = mat[0] * ( mat[5]*mat[10] - mat[9]*mat[6] )
207 - mat[1] * ( mat[4]*mat[10] - mat[8]*mat[6] )
208 + mat[2] * ( mat[4]*mat[9] - mat[8]*mat[5] );
209
210 return( det );
211}
212
213
214inline void dMatrix3Inv( const dMatrix3& ma, dMatrix3& dst )
215{
216 dReal det = dMatrix3Det( ma );
217
218 if ( dFabs( det ) < REAL(0.0005) )
219 {
220 dRSetIdentity( dst );
221 return;
222 }
223
224 dst[0] = ma[5]*ma[10] - ma[6]*ma[9] / det;
225 dst[1] = -( ma[1]*ma[10] - ma[9]*ma[2] ) / det;
226 dst[2] = ma[1]*ma[6] - ma[5]*ma[2] / det;
227
228 dst[4] = -( ma[4]*ma[10] - ma[6]*ma[8] ) / det;
229 dst[5] = ma[0]*ma[10] - ma[8]*ma[2] / det;
230 dst[6] = -( ma[0]*ma[6] - ma[4]*ma[2] ) / det;
231
232 dst[8] = ma[4]*ma[9] - ma[8]*ma[5] / det;
233 dst[9] = -( ma[0]*ma[9] - ma[8]*ma[1] ) / det;
234 dst[10] = ma[0]*ma[5] - ma[1]*ma[4] / det;
235}
236
237inline void dQuatTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest)
238{
239
240 // Nguyen Binh : this code seem to be the fastest.
241 dReal x0 = source[0] * quat[0] + source[2] * quat[2] - source[1] * quat[3];
242 dReal x1 = source[1] * quat[0] + source[0] * quat[3] - source[2] * quat[1];
243 dReal x2 = source[2] * quat[0] + source[1] * quat[1] - source[0] * quat[2];
244 dReal x3 = source[0] * quat[1] + source[1] * quat[2] + source[2] * quat[3];
245
246 dest[0] = quat[0] * x0 + quat[1] * x3 + quat[2] * x2 - quat[3] * x1;
247 dest[1] = quat[0] * x1 + quat[2] * x3 + quat[3] * x0 - quat[1] * x2;
248 dest[2] = quat[0] * x2 + quat[3] * x3 + quat[1] * x1 - quat[2] * x0;
249
250 /*
251 // nVidia SDK implementation
252 dVector3 uv, uuv;
253 dVector3 qvec;
254 qvec[0] = quat[1];
255 qvec[1] = quat[2];
256 qvec[2] = quat[3];
257
258 dVector3Cross(qvec,source,uv);
259 dVector3Cross(qvec,uv,uuv);
260
261 dVector3Scale(uv,REAL(2.0)*quat[0]);
262 dVector3Scale(uuv,REAL(2.0));
263
264 dest[0] = source[0] + uv[0] + uuv[0];
265 dest[1] = source[1] + uv[1] + uuv[1];
266 dest[2] = source[2] + uv[2] + uuv[2];
267 */
268}
269
270inline void dQuatInvTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest)
271{
272
273 dReal norm = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] + quat[3]*quat[3];
274
275 if (norm > REAL(0.0))
276 {
277 dQuaternion invQuat;
278 invQuat[0] = quat[0] / norm;
279 invQuat[1] = -quat[1] / norm;
280 invQuat[2] = -quat[2] / norm;
281 invQuat[3] = -quat[3] / norm;
282
283 dQuatTransform(invQuat,source,dest);
284
285 }
286 else
287 {
288 // Singular -> return identity
289 dVector3Copy(source,dest);
290 }
291}
292
293inline void dGetEulerAngleFromRot(const dMatrix3& mRot,dReal& rX,dReal& rY,dReal& rZ)
294{
295 rY = asin(mRot[0 * 4 + 2]);
296 if (rY < M_PI /2)
297 {
298 if (rY > -M_PI /2)
299 {
300 rX = atan2(-mRot[1*4 + 2], mRot[2*4 + 2]);
301 rZ = atan2(-mRot[0*4 + 1], mRot[0*4 + 0]);
302 }
303 else
304 {
305 // not unique
306 rX = -atan2(mRot[1*4 + 0], mRot[1*4 + 1]);
307 rZ = REAL(0.0);
308 }
309 }
310 else
311 {
312 // not unique
313 rX = atan2(mRot[1*4 + 0], mRot[1*4 + 1]);
314 rZ = REAL(0.0);
315 }
316}
317
318inline void dQuatInv(const dQuaternion& source, dQuaternion& dest)
319{
320 dReal norm = source[0]*source[0] + source[1]*source[1] + source[2]*source[2] + source[3]*source[3];
321
322 if (norm > 0.0f)
323 {
324 dest[0] = source[0] / norm;
325 dest[1] = -source[1] / norm;
326 dest[2] = -source[2] / norm;
327 dest[3] = -source[3] / norm;
328 }
329 else
330 {
331 // Singular -> return identity
332 dest[0] = REAL(1.0);
333 dest[1] = REAL(0.0);
334 dest[2] = REAL(0.0);
335 dest[3] = REAL(0.0);
336 }
337}
338
339
340#endif
diff --git a/libraries/ode-0.9/ode/src/convex.cpp b/libraries/ode-0.9/ode/src/convex.cpp
deleted file mode 100644
index db93beb..0000000
--- a/libraries/ode-0.9/ode/src/convex.cpp
+++ /dev/null
@@ -1,1294 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24Code for Convex Collision Detection
25By Rodrigo Hernandez
26*/
27//#include <algorithm>
28#include <ode/common.h>
29#include <ode/collision.h>
30#include <ode/matrix.h>
31#include <ode/rotation.h>
32#include <ode/odemath.h>
33#include "collision_kernel.h"
34#include "collision_std.h"
35#include "collision_util.h"
36
37#ifdef _MSC_VER
38#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
39#endif
40
41#if _MSC_VER <= 1200
42#define dMIN(A,B) ((A)>(B) ? B : A)
43#define dMAX(A,B) ((A)>(B) ? A : B)
44#else
45#define dMIN(A,B) std::min(A,B)
46#define dMAX(A,B) std::max(A,B)
47#endif
48
49//****************************************************************************
50// Convex public API
51dxConvex::dxConvex (dSpaceID space,
52 dReal *_planes,
53 unsigned int _planecount,
54 dReal *_points,
55 unsigned int _pointcount,
56 unsigned int *_polygons) :
57 dxGeom (space,1)
58{
59 dAASSERT (_planes != NULL);
60 dAASSERT (_points != NULL);
61 dAASSERT (_polygons != NULL);
62 //fprintf(stdout,"dxConvex Constructor planes %X\n",_planes);
63 type = dConvexClass;
64 planes = _planes;
65 planecount = _planecount;
66 // we need points as well
67 points = _points;
68 pointcount = _pointcount;
69 polygons=_polygons;
70 FillEdges();
71}
72
73
74void dxConvex::computeAABB()
75{
76 // this can, and should be optimized
77 dVector3 point;
78 dMULTIPLY0_331 (point,final_posr->R,points);
79 aabb[0] = point[0]+final_posr->pos[0];
80 aabb[1] = point[0]+final_posr->pos[0];
81 aabb[2] = point[1]+final_posr->pos[1];
82 aabb[3] = point[1]+final_posr->pos[1];
83 aabb[4] = point[2]+final_posr->pos[2];
84 aabb[5] = point[2]+final_posr->pos[2];
85 for(unsigned int i=3;i<(pointcount*3);i+=3)
86 {
87 dMULTIPLY0_331 (point,final_posr->R,&points[i]);
88 aabb[0] = dMIN(aabb[0],point[0]+final_posr->pos[0]);
89 aabb[1] = dMAX(aabb[1],point[0]+final_posr->pos[0]);
90 aabb[2] = dMIN(aabb[2],point[1]+final_posr->pos[1]);
91 aabb[3] = dMAX(aabb[3],point[1]+final_posr->pos[1]);
92 aabb[4] = dMIN(aabb[4],point[2]+final_posr->pos[2]);
93 aabb[5] = dMAX(aabb[5],point[2]+final_posr->pos[2]);
94 }
95}
96
97/*! \brief Populates the edges set, should be called only once whenever
98 the polygon array gets updated */
99void dxConvex::FillEdges()
100{
101 unsigned int *points_in_poly=polygons;
102 unsigned int *index=polygons+1;
103 for(unsigned int i=0;i<planecount;++i)
104 {
105 //fprintf(stdout,"Points in Poly: %d\n",*points_in_poly);
106 for(unsigned int j=0;j<*points_in_poly;++j)
107 {
108 edges.insert(edge(dMIN(index[j],index[(j+1)%*points_in_poly]),
109 dMAX(index[j],index[(j+1)%*points_in_poly])));
110 //fprintf(stdout,"Insert %d-%d\n",index[j],index[(j+1)%*points_in_poly]);
111 }
112 points_in_poly+=(*points_in_poly+1);
113 index=points_in_poly+1;
114 }
115 /*
116 fprintf(stdout,"Edge Count: %d\n",edges.size());
117 for(std::set<edge>::iterator it=edges.begin();
118 it!=edges.end();
119 ++it)
120 {
121 fprintf(stdout,"Edge: %d-%d\n",it->first,it->second);
122 }
123 */
124}
125
126dGeomID dCreateConvex (dSpaceID space,dReal *_planes,unsigned int _planecount,
127 dReal *_points,
128 unsigned int _pointcount,
129 unsigned int *_polygons)
130{
131 //fprintf(stdout,"dxConvex dCreateConvex\n");
132 return new dxConvex(space,_planes, _planecount,
133 _points,
134 _pointcount,
135 _polygons);
136}
137
138void dGeomSetConvex (dGeomID g,dReal *_planes,unsigned int _planecount,
139 dReal *_points,
140 unsigned int _pointcount,
141 unsigned int *_polygons)
142{
143 //fprintf(stdout,"dxConvex dGeomSetConvex\n");
144 dUASSERT (g && g->type == dConvexClass,"argument not a convex shape");
145 dxConvex *s = (dxConvex*) g;
146 s->planes = _planes;
147 s->planecount = _planecount;
148 s->points = _points;
149 s->pointcount = _pointcount;
150 s->polygons=_polygons;
151}
152
153//****************************************************************************
154// Helper Inlines
155//
156
157/*! \brief Returns Whether or not the segment ab intersects plane p
158 \param a origin of the segment
159 \param b segment destination
160 \param p plane to test for intersection
161 \param t returns the time "t" in the segment ray that gives us the intersecting
162 point
163 \param q returns the intersection point
164 \return true if there is an intersection, otherwise false.
165*/
166bool IntersectSegmentPlane(dVector3 a,
167 dVector3 b,
168 dVector4 p,
169 dReal &t,
170 dVector3 q)
171{
172 // Compute the t value for the directed line ab intersecting the plane
173 dVector3 ab;
174 ab[0]= b[0] - a[0];
175 ab[1]= b[1] - a[1];
176 ab[2]= b[2] - a[2];
177
178 t = (p[3] - dDOT(p,a)) / dDOT(p,ab);
179
180 // If t in [0..1] compute and return intersection point
181 if (t >= 0.0 && t <= 1.0)
182 {
183 q[0] = a[0] + t * ab[0];
184 q[1] = a[1] + t * ab[1];
185 q[2] = a[2] + t * ab[2];
186 return true;
187 }
188 // Else no intersection
189 return false;
190}
191
192/*! \brief Returns the Closest Point in Ray 1 to Ray 2
193 \param Origin1 The origin of Ray 1
194 \param Direction1 The direction of Ray 1
195 \param Origin1 The origin of Ray 2
196 \param Direction1 The direction of Ray 3
197 \param t the time "t" in Ray 1 that gives us the closest point
198 (closest_point=Origin1+(Direction*t).
199 \return true if there is a closest point, false if the rays are paralell.
200*/
201inline bool ClosestPointInRay(const dVector3 Origin1,
202 const dVector3 Direction1,
203 const dVector3 Origin2,
204 const dVector3 Direction2,
205 dReal& t)
206{
207 dVector3 w = {Origin1[0]-Origin2[0],
208 Origin1[1]-Origin2[1],
209 Origin1[2]-Origin2[2]};
210 dReal a = dDOT(Direction1 , Direction1);
211 dReal b = dDOT(Direction1 , Direction2);
212 dReal c = dDOT(Direction2 , Direction2);
213 dReal d = dDOT(Direction1 , w);
214 dReal e = dDOT(Direction2 , w);
215 dReal denominator = (a*c)-(b*b);
216 if(denominator==0.0f)
217 {
218 return false;
219 }
220 t = ((a*e)-(b*d))/denominator;
221 return true;
222}
223
224/*! \brief Returns the Ray on which 2 planes intersect if they do.
225 \param p1 Plane 1
226 \param p2 Plane 2
227 \param p Contains the origin of the ray upon returning if planes intersect
228 \param d Contains the direction of the ray upon returning if planes intersect
229 \return true if the planes intersect, false if paralell.
230*/
231inline bool IntersectPlanes(const dVector4 p1, const dVector4 p2, dVector3 p, dVector3 d)
232{
233 // Compute direction of intersection line
234 //Cross(p1, p2,d);
235 dCROSS(d,=,p1,p2);
236
237 // If d is (near) zero, the planes are parallel (and separated)
238 // or coincident, so they're not considered intersecting
239 dReal denom = dDOT(d, d);
240 if (denom < dEpsilon) return false;
241
242 dVector3 n;
243 n[0]=p1[3]*p2[0] - p2[3]*p1[0];
244 n[1]=p1[3]*p2[1] - p2[3]*p1[1];
245 n[2]=p1[3]*p2[2] - p2[3]*p1[2];
246 // Compute point on intersection line
247 //Cross(n, d,p);
248 dCROSS(p,=,n,d);
249 p[0]/=denom;
250 p[1]/=denom;
251 p[2]/=denom;
252 return true;
253}
254
255/*! \brief Finds out if a point lies inside a 2D polygon
256 \param p Point to test
257 \param polygon a pointer to the start of the convex polygon index buffer
258 \param out the closest point in the polygon if the point is not inside
259 \return true if the point lies inside of the polygon, false if not.
260*/
261inline bool IsPointInPolygon(dVector3 p,
262 unsigned int *polygon,
263 dxConvex *convex,
264 dVector3 out)
265{
266 // p is the point we want to check,
267 // polygon is a pointer to the polygon we
268 // are checking against, remember it goes
269 // number of vertices then that many indexes
270 // out returns the closest point on the border of the
271 // polygon if the point is not inside it.
272 size_t pointcount=polygon[0];
273 dVector3 a;
274 dVector3 b;
275 dVector3 c;
276 dVector3 ab;
277 dVector3 ac;
278 dVector3 ap;
279 dVector3 bp;
280 dReal d1;
281 dReal d2;
282 dReal d3;
283 dReal d4;
284 dReal vc;
285 polygon++; // skip past pointcount
286 for(size_t i=0;i<pointcount;++i)
287 {
288 dMULTIPLY0_331 (a,convex->final_posr->R,&convex->points[(polygon[i]*3)]);
289 a[0]=convex->final_posr->pos[0]+a[0];
290 a[1]=convex->final_posr->pos[1]+a[1];
291 a[2]=convex->final_posr->pos[2]+a[2];
292
293 dMULTIPLY0_331 (b,convex->final_posr->R,
294 &convex->points[(polygon[(i+1)%pointcount]*3)]);
295 b[0]=convex->final_posr->pos[0]+b[0];
296 b[1]=convex->final_posr->pos[1]+b[1];
297 b[2]=convex->final_posr->pos[2]+b[2];
298
299 dMULTIPLY0_331 (c,convex->final_posr->R,
300 &convex->points[(polygon[(i+2)%pointcount]*3)]);
301 c[0]=convex->final_posr->pos[0]+c[0];
302 c[1]=convex->final_posr->pos[1]+c[1];
303 c[2]=convex->final_posr->pos[2]+c[2];
304
305 ab[0] = b[0] - a[0];
306 ab[1] = b[1] - a[1];
307 ab[2] = b[2] - a[2];
308 ac[0] = c[0] - a[0];
309 ac[1] = c[1] - a[1];
310 ac[2] = c[2] - a[2];
311 ap[0] = p[0] - a[0];
312 ap[1] = p[1] - a[1];
313 ap[2] = p[2] - a[2];
314 d1 = dDOT(ab,ap);
315 d2 = dDOT(ac,ap);
316 if (d1 <= 0.0f && d2 <= 0.0f)
317 {
318 out[0]=a[0];
319 out[1]=a[1];
320 out[2]=a[2];
321 return false;
322 }
323 bp[0] = p[0] - b[0];
324 bp[1] = p[1] - b[1];
325 bp[2] = p[2] - b[2];
326 d3 = dDOT(ab,bp);
327 d4 = dDOT(ac,bp);
328 if (d3 >= 0.0f && d4 <= d3)
329 {
330 out[0]=b[0];
331 out[1]=b[1];
332 out[2]=b[2];
333 return false;
334 }
335 vc = d1*d4 - d3*d2;
336 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f)
337 {
338 dReal v = d1 / (d1 - d3);
339 out[0] = a[0] + (ab[0]*v);
340 out[1] = a[1] + (ab[1]*v);
341 out[2] = a[2] + (ab[2]*v);
342 return false;
343 }
344 }
345 return true;
346}
347
348int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags,
349 dContactGeom *contact, int skip)
350{
351 dIASSERT (skip >= (int)sizeof(dContactGeom));
352 dIASSERT (o1->type == dConvexClass);
353 dIASSERT (o2->type == dPlaneClass);
354 dIASSERT ((flags & NUMC_MASK) >= 1);
355
356 dxConvex *Convex = (dxConvex*) o1;
357 dxPlane *Plane = (dxPlane*) o2;
358 unsigned int contacts=0;
359 unsigned int maxc = flags & NUMC_MASK;
360 dVector3 v2;
361
362#define LTEQ_ZERO 0x10000000
363#define GTEQ_ZERO 0x20000000
364#define BOTH_SIGNS (LTEQ_ZERO | GTEQ_ZERO)
365 dIASSERT((BOTH_SIGNS & NUMC_MASK) == 0); // used in conditional operator later
366
367 unsigned int totalsign = 0;
368 for(unsigned int i=0;i<Convex->pointcount;++i)
369 {
370 dMULTIPLY0_331 (v2,Convex->final_posr->R,&Convex->points[(i*3)]);
371 dVector3Add(Convex->final_posr->pos, v2, v2);
372
373 unsigned int distance2sign = GTEQ_ZERO;
374 dReal distance2 = dVector3Dot(Plane->p, v2) - Plane->p[3]; // Ax + By + Cz - D
375 if((distance2 <= REAL(0.0)))
376 {
377 distance2sign = distance2 != REAL(0.0) ? LTEQ_ZERO : BOTH_SIGNS;
378
379 if (contacts != maxc)
380 {
381 dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip);
382 dVector3Copy(Plane->p, target->normal);
383 dVector3Copy(v2, target->pos);
384 target->depth = -distance2;
385 target->g1 = Convex;
386 target->g2 = Plane;
387 contacts++;
388 }
389 }
390
391 // Take new sign into account
392 totalsign |= distance2sign;
393 // Check if contacts are full and both signs have been already found
394 if ((contacts ^ maxc | totalsign) == BOTH_SIGNS) // harder to comprehend but requires one register less
395 {
396 break; // Nothing can be changed any more
397 }
398 }
399 if (totalsign == BOTH_SIGNS) return contacts;
400 return 0;
401#undef BOTH_SIGNS
402#undef GTEQ_ZERO
403#undef LTEQ_ZERO
404}
405
406int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags,
407 dContactGeom *contact, int skip)
408{
409 dIASSERT (skip >= (int)sizeof(dContactGeom));
410 dIASSERT (o1->type == dSphereClass);
411 dIASSERT (o2->type == dConvexClass);
412 dIASSERT ((flags & NUMC_MASK) >= 1);
413
414 dxSphere *Sphere = (dxSphere*) o1;
415 dxConvex *Convex = (dxConvex*) o2;
416 dReal dist,closestdist=dInfinity;
417 dVector4 plane;
418 // dVector3 contactpoint;
419 dVector3 offsetpos,out,temp;
420 unsigned int *pPoly=Convex->polygons;
421 int closestplane;
422 bool sphereinside=true;
423 /*
424 Do a good old sphere vs plane check first,
425 if a collision is found then check if the contact point
426 is within the polygon
427 */
428 // offset the sphere final_posr->position into the convex space
429 offsetpos[0]=Sphere->final_posr->pos[0]-Convex->final_posr->pos[0];
430 offsetpos[1]=Sphere->final_posr->pos[1]-Convex->final_posr->pos[1];
431 offsetpos[2]=Sphere->final_posr->pos[2]-Convex->final_posr->pos[2];
432 //fprintf(stdout,"Begin Check\n");
433 for(unsigned int i=0;i<Convex->planecount;++i)
434 {
435 // apply rotation to the plane
436 dMULTIPLY0_331(plane,Convex->final_posr->R,&Convex->planes[(i*4)]);
437 plane[3]=(&Convex->planes[(i*4)])[3];
438 // Get the distance from the sphere origin to the plane
439 dist = dVector3Dot(plane, offsetpos) - plane[3]; // Ax + By + Cz - D
440 if(dist>0)
441 {
442 // if we get here, we know the center of the sphere is
443 // outside of the convex hull.
444 if(dist<Sphere->radius)
445 {
446 // if we get here we know the sphere surface penetrates
447 // the plane
448 if(IsPointInPolygon(Sphere->final_posr->pos,pPoly,Convex,out))
449 {
450 // finally if we get here we know that the
451 // sphere is directly touching the inside of the polyhedron
452 //fprintf(stdout,"Contact! distance=%f\n",dist);
453 contact->normal[0] = plane[0];
454 contact->normal[1] = plane[1];
455 contact->normal[2] = plane[2];
456 contact->pos[0] = Sphere->final_posr->pos[0]+
457 (-contact->normal[0]*Sphere->radius);
458 contact->pos[1] = Sphere->final_posr->pos[1]+
459 (-contact->normal[1]*Sphere->radius);
460 contact->pos[2] = Sphere->final_posr->pos[2]+
461 (-contact->normal[2]*Sphere->radius);
462 contact->depth = Sphere->radius-dist;
463 contact->g1 = Sphere;
464 contact->g2 = Convex;
465 return 1;
466 }
467 else
468 {
469 // the sphere may not be directly touching
470 // the polyhedron, but it may be touching
471 // a point or an edge, if the distance between
472 // the closest point on the poly (out) and the
473 // center of the sphere is less than the sphere
474 // radius we have a hit.
475 temp[0] = (Sphere->final_posr->pos[0]-out[0]);
476 temp[1] = (Sphere->final_posr->pos[1]-out[1]);
477 temp[2] = (Sphere->final_posr->pos[2]-out[2]);
478 dist=(temp[0]*temp[0])+(temp[1]*temp[1])+(temp[2]*temp[2]);
479 // avoid the sqrt unless really necesary
480 if(dist<(Sphere->radius*Sphere->radius))
481 {
482 // We got an indirect hit
483 dist=dSqrt(dist);
484 contact->normal[0] = temp[0]/dist;
485 contact->normal[1] = temp[1]/dist;
486 contact->normal[2] = temp[2]/dist;
487 contact->pos[0] = Sphere->final_posr->pos[0]+
488 (-contact->normal[0]*Sphere->radius);
489 contact->pos[1] = Sphere->final_posr->pos[1]+
490 (-contact->normal[1]*Sphere->radius);
491 contact->pos[2] = Sphere->final_posr->pos[2]+
492 (-contact->normal[2]*Sphere->radius);
493 contact->depth = Sphere->radius-dist;
494 contact->g1 = Sphere;
495 contact->g2 = Convex;
496 return 1;
497 }
498 }
499 }
500 sphereinside=false;
501 }
502 if(sphereinside)
503 {
504 if(closestdist>dFabs(dist))
505 {
506 closestdist=dFabs(dist);
507 closestplane=i;
508 }
509 }
510 pPoly+=pPoly[0]+1;
511 }
512 if(sphereinside)
513 {
514 // if the center of the sphere is inside
515 // the Convex, we need to pop it out
516 dMULTIPLY0_331(contact->normal,
517 Convex->final_posr->R,
518 &Convex->planes[(closestplane*4)]);
519 contact->pos[0] = Sphere->final_posr->pos[0];
520 contact->pos[1] = Sphere->final_posr->pos[1];
521 contact->pos[2] = Sphere->final_posr->pos[2];
522 contact->depth = closestdist+Sphere->radius;
523 contact->g1 = Sphere;
524 contact->g2 = Convex;
525 return 1;
526 }
527 return 0;
528}
529
530int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags,
531 dContactGeom *contact, int skip)
532{
533 dIASSERT (skip >= (int)sizeof(dContactGeom));
534 dIASSERT (o1->type == dConvexClass);
535 dIASSERT (o2->type == dBoxClass);
536 dIASSERT ((flags & NUMC_MASK) >= 1);
537
538 dxConvex *Convex = (dxConvex*) o1;
539 dxBox *Box = (dxBox*) o2;
540
541 return 0;
542}
543
544int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2,
545 int flags, dContactGeom *contact, int skip)
546{
547 dIASSERT (skip >= (int)sizeof(dContactGeom));
548 dIASSERT (o1->type == dConvexClass);
549 dIASSERT (o2->type == dCapsuleClass);
550 dIASSERT ((flags & NUMC_MASK) >= 1);
551
552 dxConvex *Convex = (dxConvex*) o1;
553 dxCapsule *Capsule = (dxCapsule*) o2;
554
555 return 0;
556}
557
558/*!
559 \brief Retrieves the proper convex and plane index between 2 convex objects.
560
561 Seidel's Algorithm does not discriminate between 2 different Convex Hulls,
562 it only cares about planes, so we feed it the planes of Convex 1 followed
563 by the planes of Convex 2 as a single collection of planes,
564 given an index into the single collection,
565 this function determines the correct convex object and index to retrieve
566 the current plane.
567
568 \param c1 Convex 1
569 \param c2 Convex 2
570 \param i Plane Index to retrieve
571 \param index contains the translated index uppon return
572 \return a pointer to the convex object containing plane index "i"
573*/
574inline dxConvex* GetPlaneIndex(dxConvex& c1,
575 dxConvex& c2,
576 unsigned int i,unsigned int& index)
577{
578 if(i>=c1.planecount)
579 {
580 index = i-c1.planecount;
581 return &c2;
582 }
583 index=i;
584 return &c1;
585}
586
587inline void dumpplanes(dxConvex& cvx)
588{
589 // This is just a dummy debug function
590 dVector4 plane;
591 fprintf(stdout,"DUMP PLANES\n");
592 for (unsigned int i=0;i<cvx.planecount;++i)
593 {
594 dMULTIPLY0_331(plane,cvx.final_posr->R,&cvx.planes[(i*4)]);
595 // Translate
596 plane[3]=
597 (cvx.planes[(i*4)+3])+
598 ((plane[0] * cvx.final_posr->pos[0]) +
599 (plane[1] * cvx.final_posr->pos[1]) +
600 (plane[2] * cvx.final_posr->pos[2]));
601 fprintf(stdout,"%f %f %f %f\n",plane[0],plane[1],plane[2],plane[3]);
602 }
603}
604
605// this variable is for debuggin purpuses only, should go once everything works
606static bool hit=false;
607
608/*
609 \brief Tests whether 2 convex objects collide
610
611 Seidel's algorithm is a method to solve linear programs,
612 it finds the optimum vertex "v" of a set of functions,
613 in our case, the set of functions are the plane functions
614 for the 2 convex objects being tested.
615 We don't really care about the value optimum vertex though,
616 but the 2 convex objects only collide if this vertex exists,
617 otherwise, the set of functions is said to be "empty" or "void".
618
619 Seidel's Original algorithm is recursive and not bound to any number
620 of dimensions, the one I present here is Iterative rather than recursive
621 and bound to 3 dimensions, which is what we care about.
622
623 If you're interested (and you should be!) on the algorithm, the paper
624 by Raimund Seidel himself should explain a lot better than I did, you can
625 find it here: http://www.cs.berkeley.edu/~jrs/meshpapers/SeidelLP.pdf
626
627 If posible, read the section about Linear Programming in
628 Christer Ericson's RealTime Collision Detection book.
629
630 \note currently there seem to be some issues with this function since
631 it doesn't detect collisions except for the most simple tests :(.
632*/
633bool SeidelLP(dxConvex& cvx1,dxConvex& cvx2)
634{
635 dVector3 c={1,0,0}; // The Objective vector can be anything
636 dVector3 solution; // We dont really need the solution so its local
637 dxConvex *cvx;
638 unsigned int index;
639 unsigned int planecount=cvx1.planecount+cvx2.planecount;
640 dReal sum,min,max,med;
641 dVector3 c1; // ,c2;
642 dVector4 aoveral,aoveram; // these will contain cached computations
643 unsigned int l,m,n; // l and m are the axes to the zerod dimensions, n is the axe for the last dimension
644 unsigned int i,j,k;
645 dVector4 eq1,eq2,eq3; // cached equations for 3d,2d and 1d respectivelly
646 // Get the support mapping for a HUGE bounding box in direction c
647 solution[0]= (c[0]>0) ? dInfinity : -dInfinity;
648 solution[1]= (c[1]>0) ? dInfinity : -dInfinity;
649 solution[2]= (c[2]>0) ? dInfinity : -dInfinity;
650 for( i=0;i<planecount;++i)
651 {
652 // Isolate plane equation
653 cvx=GetPlaneIndex(cvx1,cvx2,i,index);
654 // Rotate
655 dMULTIPLY0_331(eq1,cvx->final_posr->R,&cvx->planes[(index*4)]);
656
657 // Translate
658 eq1[3]=(cvx->planes[(index*4)+3])+
659 ((eq1[0] * cvx->final_posr->pos[0]) +
660 (eq1[1] * cvx->final_posr->pos[1]) +
661 (eq1[2] * cvx->final_posr->pos[2]));
662 // if(!hit)
663 // {
664 // fprintf(stdout,"Plane I %d: %f %f %f %f\n",i,
665 // cvx->planes[(index*4)+0],
666 // cvx->planes[(index*4)+1],
667 // cvx->planes[(index*4)+2],
668 // cvx->planes[(index*4)+3]);
669 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",i,
670 // eq1[0],
671 // eq1[1],eq1[2],eq1[3]);
672 // fprintf(stdout,"POS %f,%f,%f\n",
673 // cvx->final_posr->pos[0],
674 // cvx->final_posr->pos[1],
675 // cvx->final_posr->pos[2]);
676 // }
677 // find if the solution is behind the current plane
678 sum=
679 ((eq1[0]*solution[0])+
680 (eq1[1]*solution[1])+
681 (eq1[2]*solution[2]))-eq1[3];
682 // if not we need to discard the current solution
683 if(sum>0)
684 {
685 // go down a dimension by eliminating a variable
686 // first find l
687 l=0;
688 for( j=0;j<3;++j)
689 {
690 if(fabs(eq1[j])>fabs(eq1[l]))
691 {
692 l=j;
693 }
694 }
695 if(eq1[l]==0)
696 {
697 if(!hit)
698 {
699 fprintf(stdout,"Plane %d: %f %f %f %f is invalid\n",i,
700 eq1[0],eq1[1],eq1[2],eq1[3]);
701 }
702 return false;
703 }
704 // then compute a/a[l] c1 and solution
705 aoveral[0]=eq1[0]/eq1[l];
706 aoveral[1]=eq1[1]/eq1[l];
707 aoveral[2]=eq1[2]/eq1[l];
708 aoveral[3]=eq1[3]/eq1[l];
709 c1[0]=c[0]-((c[l]/eq1[l])*eq1[0]);
710 c1[1]=c[1]-((c[l]/eq1[l])*eq1[1]);
711 c1[2]=c[2]-((c[l]/eq1[l])*eq1[2]);
712 solution[0]=solution[0]-((solution[l]/eq1[l])*eq1[0]);
713 solution[1]=solution[1]-((solution[l]/eq1[l])*eq1[1]);
714 solution[2]=solution[2]-((solution[l]/eq1[l])*eq1[2]);
715 // iterate a to get the new equations with the help of a/a[l]
716 for( j=0;j<planecount;++j)
717 {
718 if(i!=j)
719 {
720 cvx=GetPlaneIndex(cvx1,cvx2,j,index);
721 // Rotate
722 dMULTIPLY0_331(eq2,cvx->final_posr->R,&cvx->planes[(index*4)]);
723 // Translate
724 eq2[3]=(cvx->planes[(index*4)+3])+
725 ((eq2[0] * cvx->final_posr->pos[0]) +
726 (eq2[1] * cvx->final_posr->pos[1]) +
727 (eq2[2] * cvx->final_posr->pos[2]));
728
729 // if(!hit)
730 // {
731 // fprintf(stdout,"Plane J %d: %f %f %f %f\n",j,
732 // cvx->planes[(index*4)+0],
733 // cvx->planes[(index*4)+1],
734 // cvx->planes[(index*4)+2],
735 // cvx->planes[(index*4)+3]);
736 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",j,
737 // eq2[0],
738 // eq2[1],
739 // eq2[2],
740 // eq2[3]);
741 // fprintf(stdout,"POS %f,%f,%f\n",
742 // cvx->final_posr->pos[0],
743 // cvx->final_posr->pos[1],
744 // cvx->final_posr->pos[2]);
745 // }
746
747 // Take The equation down a dimension
748 eq2[0]-=(cvx->planes[(index*4)+l]*aoveral[0]);
749 eq2[1]-=(cvx->planes[(index*4)+l]*aoveral[1]);
750 eq2[2]-=(cvx->planes[(index*4)+l]*aoveral[2]);
751 eq2[3]-=(cvx->planes[(index*4)+l]*aoveral[3]);
752 sum=
753 ((eq2[0]*solution[0])+
754 (eq2[1]*solution[1])+
755 (eq2[2]*solution[2]))-eq2[3];
756 if(sum>0)
757 {
758 m=0;
759 for( k=0;k<3;++k)
760 {
761 if(fabs(eq2[k])>fabs(eq2[m]))
762 {
763 m=k;
764 }
765 }
766 if(eq2[m]==0)
767 {
768 /*
769 if(!hit) fprintf(stdout,
770 "Plane %d: %f %f %f %f is invalid\n",j,
771 eq2[0],eq2[1],eq2[2],eq2[3]);
772 */
773 return false;
774 }
775 // then compute a/a[m] c1 and solution
776 aoveram[0]=eq2[0]/eq2[m];
777 aoveram[1]=eq2[1]/eq2[m];
778 aoveram[2]=eq2[2]/eq2[m];
779 aoveram[3]=eq2[3]/eq2[m];
780 c1[0]=c[0]-((c[m]/eq2[m])*eq2[0]);
781 c1[1]=c[1]-((c[m]/eq2[m])*eq2[1]);
782 c1[2]=c[2]-((c[m]/eq2[m])*eq2[2]);
783 solution[0]=solution[0]-((solution[m]/eq2[m])*eq2[0]);
784 solution[1]=solution[1]-((solution[m]/eq2[m])*eq2[1]);
785 solution[2]=solution[2]-((solution[m]/eq2[m])*eq2[2]);
786 // figure out the value for n by elimination
787 n = (l==0) ? ((m==1)? 2:1):((m==0)?((l==1)?2:1):0);
788 // iterate a to get the new equations with the help of a/a[l]
789 min=-dInfinity;
790 max=med=dInfinity;
791 for(k=0;k<planecount;++k)
792 {
793 if((i!=k)&&(j!=k))
794 {
795 cvx=GetPlaneIndex(cvx1,cvx2,k,index);
796 // Rotate
797 dMULTIPLY0_331(eq3,cvx->final_posr->R,&cvx->planes[(index*4)]);
798 // Translate
799 eq3[3]=(cvx->planes[(index*4)+3])+
800 ((eq3[0] * cvx->final_posr->pos[0]) +
801 (eq3[1] * cvx->final_posr->pos[1]) +
802 (eq3[2] * cvx->final_posr->pos[2]));
803 // if(!hit)
804 // {
805 // fprintf(stdout,"Plane K %d: %f %f %f %f\n",k,
806 // cvx->planes[(index*4)+0],
807 // cvx->planes[(index*4)+1],
808 // cvx->planes[(index*4)+2],
809 // cvx->planes[(index*4)+3]);
810 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",k,
811 // eq3[0],
812 // eq3[1],
813 // eq3[2],
814 // eq3[3]);
815 // fprintf(stdout,"POS %f,%f,%f\n",
816 // cvx->final_posr->pos[0],
817 // cvx->final_posr->pos[1],
818 // cvx->final_posr->pos[2]);
819 // }
820
821 // Take the equation Down to 1D
822 eq3[0]-=(cvx->planes[(index*4)+m]*aoveram[0]);
823 eq3[1]-=(cvx->planes[(index*4)+m]*aoveram[1]);
824 eq3[2]-=(cvx->planes[(index*4)+m]*aoveram[2]);
825 eq3[3]-=(cvx->planes[(index*4)+m]*aoveram[3]);
826 if(eq3[n]>0)
827 {
828 max=dMIN(max,eq3[3]/eq3[n]);
829 }
830 else if(eq3[n]<0)
831 {
832 min=dMAX(min,eq3[3]/eq3[n]);
833 }
834 else
835 {
836 med=dMIN(med,eq3[3]);
837 }
838 }
839 }
840 if ((max<min)||(med<0))
841 {
842 // if(!hit) fprintf(stdout,"((max<min)||(med<0)) ((%f<%f)||(%f<0))",max,min,med);
843 if(!hit)
844 {
845 dumpplanes(cvx1);
846 dumpplanes(cvx2);
847 }
848 //fprintf(stdout,"Planes %d %d\n",i,j);
849 return false;
850
851 }
852 // find the value for the solution in one dimension
853 solution[n] = (c1[n]>=0) ? max:min;
854 // lift to 2D
855 solution[m] = (eq2[3]-(eq2[n]*solution[n]))/eq2[m];
856 // lift to 3D
857 solution[l] = (eq1[3]-(eq1[m]*solution[m]+
858 eq1[n]*solution[n]))/eq1[l];
859 }
860 }
861 }
862 }
863 }
864 return true;
865}
866
867/*! \brief A Support mapping function for convex shapes
868 \param dir direction to find the Support Point for
869 \param cvx convex object to find the support point for
870 \param out the support mapping in dir.
871 */
872inline void Support(dVector3 dir,dxConvex& cvx,dVector3 out)
873{
874 unsigned int index = 0;
875 dVector3 point;
876 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points);
877 point[0]+=cvx.final_posr->pos[0];
878 point[1]+=cvx.final_posr->pos[1];
879 point[2]+=cvx.final_posr->pos[2];
880
881 dReal max = dDOT(point,dir);
882 dReal tmp;
883 for (unsigned int i = 1; i < cvx.pointcount; ++i)
884 {
885 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+(i*3));
886 point[0]+=cvx.final_posr->pos[0];
887 point[1]+=cvx.final_posr->pos[1];
888 point[2]+=cvx.final_posr->pos[2];
889 tmp = dDOT(point, dir);
890 if (tmp > max)
891 {
892 out[0]=point[0];
893 out[1]=point[1];
894 out[2]=point[2];
895 max = tmp;
896 }
897 }
898}
899
900inline void ComputeInterval(dxConvex& cvx,dVector4 axis,dReal& min,dReal& max)
901{
902 dVector3 point;
903 dReal value;
904 //fprintf(stdout,"Compute Interval Axis %f,%f,%f\n",axis[0],axis[1],axis[2]);
905 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points);
906 //fprintf(stdout,"initial point %f,%f,%f\n",point[0],point[1],point[2]);
907 point[0]+=cvx.final_posr->pos[0];
908 point[1]+=cvx.final_posr->pos[1];
909 point[2]+=cvx.final_posr->pos[2];
910 max = min = dDOT(axis,cvx.points);
911 for (unsigned int i = 1; i < cvx.pointcount; ++i)
912 {
913 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+(i*3));
914 point[0]+=cvx.final_posr->pos[0];
915 point[1]+=cvx.final_posr->pos[1];
916 point[2]+=cvx.final_posr->pos[2];
917 value=dDOT(axis,point);
918 if(value<min)
919 {
920 min=value;
921 }
922 else if(value>max)
923 {
924 max=value;
925 }
926 }
927 //fprintf(stdout,"Compute Interval Min Max %f,%f\n",min,max);
928}
929
930/*! \brief Does an axis separation test between the 2 convex shapes
931using faces and edges */
932int TestConvexIntersection(dxConvex& cvx1,dxConvex& cvx2, int flags,
933 dContactGeom *contact, int skip)
934{
935 dVector4 plane,savedplane;
936 dReal min1,max1,min2,max2,min_depth=-dInfinity;
937 dVector3 e1,e2,t;
938 int maxc = flags & NUMC_MASK; // this is causing a segfault
939 dIASSERT(maxc != 0);
940 dxConvex *g1,*g2;
941 unsigned int *pPoly;
942 dVector3 v;
943 // Test faces of cvx1 for separation
944 pPoly=cvx1.polygons;
945 for(unsigned int i=0;i<cvx1.planecount;++i)
946 {
947 // -- Apply Transforms --
948 // Rotate
949 dMULTIPLY0_331(plane,cvx1.final_posr->R,cvx1.planes+(i*4));
950 dNormalize3(plane);
951 // Translate
952 plane[3]=
953 (cvx1.planes[(i*4)+3])+
954 ((plane[0] * cvx1.final_posr->pos[0]) +
955 (plane[1] * cvx1.final_posr->pos[1]) +
956 (plane[2] * cvx1.final_posr->pos[2]));
957 ComputeInterval(cvx1,plane,min1,max1);
958 ComputeInterval(cvx2,plane,min2,max2);
959 //fprintf(stdout,"width %f\n",max1-min1);
960 if(max2<min1 || max1<min2) return 0;
961#if 1
962 // this one ON works
963 else if ((max1>min2)&&(max1<max2))
964 {
965 min_depth=max1-min2;
966 savedplane[0]=plane[0];
967 savedplane[1]=plane[1];
968 savedplane[2]=plane[2];
969 savedplane[3]=plane[3];
970 g1=&cvx2; // cvx2 moves
971 g2=&cvx1;
972 }
973#endif
974 pPoly+=pPoly[0]+1;
975 }
976 // Test faces of cvx2 for separation
977 pPoly=cvx2.polygons;
978 for(unsigned int i=0;i<cvx2.planecount;++i)
979 {
980 // fprintf(stdout,"Poly verts %d\n",pPoly[0]);
981 // -- Apply Transforms --
982 // Rotate
983 dMULTIPLY0_331(plane,
984 cvx2.final_posr->R,
985 cvx2.planes+(i*4));
986 dNormalize3(plane);
987 // Translate
988 plane[3]=
989 (cvx2.planes[(i*4)+3])+
990 ((plane[0] * cvx2.final_posr->pos[0]) +
991 (plane[1] * cvx2.final_posr->pos[1]) +
992 (plane[2] * cvx2.final_posr->pos[2]));
993 ComputeInterval(cvx2,plane,min1,max1);
994 ComputeInterval(cvx1,plane,min2,max2);
995 //fprintf(stdout,"width %f\n",max1-min1);
996 if(max2<min1 || max1<min2) return 0;
997#if 1
998 // this one ON does not work
999 else if ((max1>min2)&&(max1<max2))
1000 {
1001 min_depth=max1-min2;
1002 savedplane[0]=plane[0];
1003 savedplane[1]=plane[1];
1004 savedplane[2]=plane[2];
1005 savedplane[3]=plane[3];
1006 g1=&cvx1; // cvx1 moves
1007 g2=&cvx2;
1008 }
1009#endif
1010 pPoly+=pPoly[0]+1;
1011 }
1012 // Test cross products of pairs of edges
1013 for(std::set<edge>::iterator i = cvx1.edges.begin();
1014 i!= cvx1.edges.end();
1015 ++i)
1016 {
1017 // we only need to apply rotation here
1018 dMULTIPLY0_331 (t,cvx1.final_posr->R,cvx1.points+(i->first*3));
1019 dMULTIPLY0_331 (e1,cvx1.final_posr->R,cvx1.points+(i->second*3));
1020 e1[0]-=t[0];
1021 e1[1]-=t[1];
1022 e1[2]-=t[2];
1023 for(std::set<edge>::iterator j = cvx2.edges.begin();
1024 j!= cvx2.edges.end();
1025 ++j)
1026 {
1027 // we only need to apply rotation here
1028 dMULTIPLY0_331 (t,cvx2.final_posr->R,cvx2.points+(j->first*3));
1029 dMULTIPLY0_331 (e2,cvx2.final_posr->R,cvx2.points+(j->second*3));
1030 e2[0]-=t[0];
1031 e2[1]-=t[1];
1032 e2[2]-=t[2];
1033 dCROSS(plane,=,e1,e2);
1034 plane[3]=0;
1035 ComputeInterval(cvx1,plane,min1,max1);
1036 ComputeInterval(cvx2,plane,min2,max2);
1037 if(max2<min1 || max1 < min2) return 0;
1038 }
1039 }
1040/* -- uncomment if you are debugging
1041 static int cvxhit=0;
1042 if(cvxhit<2)
1043 fprintf(stdout,"Plane: %f,%f,%f,%f\n",
1044 (double)savedplane[0],
1045 (double)savedplane[1],
1046 (double)savedplane[2],
1047 (double)savedplane[3]);
1048*/
1049 // If we get here, there was a collision
1050 int contacts=0;
1051 for(unsigned int i=0;i<g1->pointcount;++i)
1052 {
1053 dMULTIPLY0_331 (v,g1->final_posr->R,&g1->points[(i*3)]);
1054 dVector3Add(g1->final_posr->pos, v, v);
1055
1056 dReal distance = dVector3Dot(savedplane, v) - savedplane[3]; // Ax + By + Cz - D
1057 if(distance<0)
1058 {
1059 dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip);
1060 dVector3Copy(savedplane, target->normal);
1061 dVector3Copy(v, target->pos);
1062 target->depth = -distance;
1063 target->g1 = g1;
1064 target->g2 = g2;
1065/* -- uncomment if you are debugging
1066 if(cvxhit<2)
1067 fprintf(stdout,"Contact: %f,%f,%f depth %f\n",
1068 (double)target->pos[0],
1069 (double)target->pos[1],
1070 (double)target->pos[2],
1071 (double)target->depth);
1072*/
1073 contacts++;
1074 if (contacts==maxc) break;
1075 }
1076 }
1077/* -- uncomment if you are debugging
1078 cvxhit++;
1079*/
1080
1081 return contacts;
1082}
1083
1084int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
1085 dContactGeom *contact, int skip)
1086{
1087 dIASSERT (skip >= (int)sizeof(dContactGeom));
1088 dIASSERT (o1->type == dConvexClass);
1089 dIASSERT (o2->type == dConvexClass);
1090 dIASSERT ((flags & NUMC_MASK) >= 1);
1091
1092// if(!hit) fprintf(stdout,"dCollideConvexConvex\n");
1093 dxConvex *Convex1 = (dxConvex*) o1;
1094 dxConvex *Convex2 = (dxConvex*) o2;
1095 int contacts;
1096 if(contacts=TestConvexIntersection(*Convex1,*Convex2,flags,
1097 contact,skip))
1098 {
1099 //fprintf(stdout,"We have a Hit!\n");
1100 }
1101 return contacts;
1102}
1103
1104#if 0
1105
1106int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags,
1107 dContactGeom *contact, int skip)
1108{
1109 dIASSERT (skip >= (int)sizeof(dContactGeom));
1110 dIASSERT( o1->type == dRayClass );
1111 dIASSERT( o2->type == dConvexClass );
1112 dIASSERT ((flags & NUMC_MASK) >= 1);
1113
1114 dxRay* ray = (dxRay*) o1;
1115 dxConvex* convex = (dxConvex*) o2;
1116 dVector3 origin,destination,contactpoint,out;
1117 dReal depth;
1118 dVector4 plane;
1119 unsigned int *pPoly=convex->polygons;
1120 // Calculate ray origin and destination
1121 destination[0]=0;
1122 destination[1]=0;
1123 destination[2]= ray->length;
1124 // -- Rotate --
1125 dMULTIPLY0_331(destination,ray->final_posr->R,destination);
1126 origin[0]=ray->final_posr->pos[0];
1127 origin[1]=ray->final_posr->pos[1];
1128 origin[2]=ray->final_posr->pos[2];
1129 destination[0]+=origin[0];
1130 destination[1]+=origin[1];
1131 destination[2]+=origin[2];
1132 for(int i=0;i<convex->planecount;++i)
1133 {
1134 // Rotate
1135 dMULTIPLY0_331(plane,convex->final_posr->R,convex->planes+(i*4));
1136 // Translate
1137 plane[3]=
1138 (convex->planes[(i*4)+3])+
1139 ((plane[0] * convex->final_posr->pos[0]) +
1140 (plane[1] * convex->final_posr->pos[1]) +
1141 (plane[2] * convex->final_posr->pos[2]));
1142 if(IntersectSegmentPlane(origin,
1143 destination,
1144 plane,
1145 depth,
1146 contactpoint))
1147 {
1148 if(IsPointInPolygon(contactpoint,pPoly,convex,out))
1149 {
1150 contact->pos[0]=contactpoint[0];
1151 contact->pos[1]=contactpoint[1];
1152 contact->pos[2]=contactpoint[2];
1153 contact->normal[0]=plane[0];
1154 contact->normal[1]=plane[1];
1155 contact->normal[2]=plane[2];
1156 contact->depth=depth;
1157 contact->g1 = ray;
1158 contact->g2 = convex;
1159 return 1;
1160 }
1161 }
1162 pPoly+=pPoly[0]+1;
1163 }
1164 return 0;
1165}
1166
1167#else
1168
1169// Ray - Convex collider by David Walters, June 2006
1170int dCollideRayConvex( dxGeom *o1, dxGeom *o2,
1171 int flags, dContactGeom *contact, int skip )
1172{
1173 dIASSERT( skip >= (int)sizeof(dContactGeom) );
1174 dIASSERT( o1->type == dRayClass );
1175 dIASSERT( o2->type == dConvexClass );
1176 dIASSERT ((flags & NUMC_MASK) >= 1);
1177
1178 dxRay* ray = (dxRay*) o1;
1179 dxConvex* convex = (dxConvex*) o2;
1180
1181 contact->g1 = ray;
1182 contact->g2 = convex;
1183
1184 dReal alpha, beta, nsign;
1185 int flag;
1186
1187 //
1188 // Compute some useful info
1189 //
1190
1191 flag = 0; // Assume start point is behind all planes.
1192
1193 for ( unsigned int i = 0; i < convex->planecount; ++i )
1194 {
1195 // Alias this plane.
1196 dReal* plane = convex->planes + ( i * 4 );
1197
1198 // If alpha >= 0 then start point is outside of plane.
1199 alpha = dDOT( plane, ray->final_posr->pos ) - plane[3];
1200
1201 // If any alpha is positive, then
1202 // the ray start is _outside_ of the hull
1203 if ( alpha >= 0 )
1204 {
1205 flag = 1;
1206 break;
1207 }
1208 }
1209
1210 // If the ray starts inside the convex hull, then everything is flipped.
1211 nsign = ( flag ) ? REAL( 1.0 ) : REAL( -1.0 );
1212
1213
1214 //
1215 // Find closest contact point
1216 //
1217
1218 // Assume no contacts.
1219 contact->depth = dInfinity;
1220
1221 for ( unsigned int i = 0; i < convex->planecount; ++i )
1222 {
1223 // Alias this plane.
1224 dReal* plane = convex->planes + ( i * 4 );
1225
1226 // If alpha >= 0 then point is outside of plane.
1227 alpha = nsign * ( dDOT( plane, ray->final_posr->pos ) - plane[3] );
1228
1229 // Compute [ plane-normal DOT ray-normal ], (/flip)
1230 beta = dDOT13( plane, ray->final_posr->R+2 ) * nsign;
1231
1232 // Ray is pointing at the plane? ( beta < 0 )
1233 // Ray start to plane is within maximum ray length?
1234 // Ray start to plane is closer than the current best distance?
1235 if ( beta < -dEpsilon &&
1236 alpha >= 0 && alpha <= ray->length &&
1237 alpha < contact->depth )
1238 {
1239 // Compute contact point on convex hull surface.
1240 contact->pos[0] = ray->final_posr->pos[0] + alpha * ray->final_posr->R[0*4+2];
1241 contact->pos[1] = ray->final_posr->pos[1] + alpha * ray->final_posr->R[1*4+2];
1242 contact->pos[2] = ray->final_posr->pos[2] + alpha * ray->final_posr->R[2*4+2];
1243
1244 flag = 0;
1245
1246 // For all _other_ planes.
1247 for ( unsigned int j = 0; j < convex->planecount; ++j )
1248 {
1249 if ( i == j )
1250 continue; // Skip self.
1251
1252 // Alias this plane.
1253 dReal* planej = convex->planes + ( j * 4 );
1254
1255 // If beta >= 0 then start is outside of plane.
1256 beta = dDOT( planej, contact->pos ) - plane[3];
1257
1258 // If any beta is positive, then the contact point
1259 // is not on the surface of the convex hull - it's just
1260 // intersecting some part of its infinite extent.
1261 if ( beta > dEpsilon )
1262 {
1263 flag = 1;
1264 break;
1265 }
1266 }
1267
1268 // Contact point isn't outside hull's surface? then it's a good contact!
1269 if ( flag == 0 )
1270 {
1271 // Store the contact normal, possibly flipped.
1272 contact->normal[0] = nsign * plane[0];
1273 contact->normal[1] = nsign * plane[1];
1274 contact->normal[2] = nsign * plane[2];
1275
1276 // Store depth
1277 contact->depth = alpha;
1278
1279 if ((flags & CONTACTS_UNIMPORTANT) && contact->depth <= ray->length )
1280 {
1281 // Break on any contact if contacts are not important
1282 break;
1283 }
1284 }
1285 }
1286 }
1287
1288 // Contact?
1289 return ( contact->depth <= ray->length );
1290}
1291
1292#endif
1293
1294//<-- Convex Collision
diff --git a/libraries/ode-0.9/ode/src/cylinder.cpp b/libraries/ode-0.9/ode/src/cylinder.cpp
deleted file mode 100644
index 39a6cf3..0000000
--- a/libraries/ode-0.9/ode/src/cylinder.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45// flat cylinder public API
46
47dxCylinder::dxCylinder (dSpaceID space, dReal _radius, dReal _length) :
48dxGeom (space,1)
49{
50 dAASSERT (_radius > 0 && _length > 0);
51 type = dCylinderClass;
52 radius = _radius;
53 lz = _length;
54}
55
56
57void dxCylinder::computeAABB()
58{
59 const dMatrix3& R = final_posr->R;
60 const dVector3& pos = final_posr->pos;
61
62 dReal xrange = dFabs (R[0] * radius) + dFabs (R[1] * radius) + REAL(0.5)* dFabs (R[2] *
63 lz);
64 dReal yrange = dFabs (R[4] * radius) + dFabs (R[5] * radius) + REAL(0.5)* dFabs (R[6] *
65 lz);
66 dReal zrange = dFabs (R[8] * radius) + dFabs (R[9] * radius) + REAL(0.5)* dFabs (R[10] *
67 lz);
68 aabb[0] = pos[0] - xrange;
69 aabb[1] = pos[0] + xrange;
70 aabb[2] = pos[1] - yrange;
71 aabb[3] = pos[1] + yrange;
72 aabb[4] = pos[2] - zrange;
73 aabb[5] = pos[2] + zrange;
74}
75
76
77dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length)
78{
79 return new dxCylinder (space,radius,length);
80}
81
82void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length)
83{
84 dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder");
85 dAASSERT (radius > 0 && length > 0);
86 dxCylinder *c = (dxCylinder*) cylinder;
87 c->radius = radius;
88 c->lz = length;
89 dGeomMoved (cylinder);
90}
91
92void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length)
93{
94 dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder");
95 dxCylinder *c = (dxCylinder*) cylinder;
96 *radius = c->radius;
97 *length = c->lz;
98}
99
100
diff --git a/libraries/ode-0.9/ode/src/error.cpp b/libraries/ode-0.9/ode/src/error.cpp
deleted file mode 100644
index 9b33db5..0000000
--- a/libraries/ode-0.9/ode/src/error.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/error.h>
25
26
27static dMessageFunction *error_function = 0;
28static dMessageFunction *debug_function = 0;
29static dMessageFunction *message_function = 0;
30
31
32extern "C" void dSetErrorHandler (dMessageFunction *fn)
33{
34 error_function = fn;
35}
36
37
38extern "C" void dSetDebugHandler (dMessageFunction *fn)
39{
40 debug_function = fn;
41}
42
43
44extern "C" void dSetMessageHandler (dMessageFunction *fn)
45{
46 message_function = fn;
47}
48
49
50extern "C" dMessageFunction *dGetErrorHandler()
51{
52 return error_function;
53}
54
55
56extern "C" dMessageFunction *dGetDebugHandler()
57{
58 return debug_function;
59}
60
61
62extern "C" dMessageFunction *dGetMessageHandler()
63{
64 return message_function;
65}
66
67
68static void printMessage (int num, const char *msg1, const char *msg2,
69 va_list ap)
70{
71 fflush (stderr);
72 fflush (stdout);
73 if (num) fprintf (stderr,"\n%s %d: ",msg1,num);
74 else fprintf (stderr,"\n%s: ",msg1);
75 vfprintf (stderr,msg2,ap);
76 fprintf (stderr,"\n");
77 fflush (stderr);
78}
79
80//****************************************************************************
81// unix
82
83#ifndef WIN32
84
85extern "C" void dError (int num, const char *msg, ...)
86{
87 va_list ap;
88 va_start (ap,msg);
89 if (error_function) error_function (num,msg,ap);
90 else printMessage (num,"ODE Error",msg,ap);
91 exit (1);
92}
93
94
95extern "C" void dDebug (int num, const char *msg, ...)
96{
97 va_list ap;
98 va_start (ap,msg);
99 if (debug_function) debug_function (num,msg,ap);
100 else printMessage (num,"ODE INTERNAL ERROR",msg,ap);
101 // *((char *)0) = 0; ... commit SEGVicide
102 abort();
103}
104
105
106extern "C" void dMessage (int num, const char *msg, ...)
107{
108 va_list ap;
109 va_start (ap,msg);
110 if (message_function) message_function (num,msg,ap);
111 else printMessage (num,"ODE Message",msg,ap);
112}
113
114#endif
115
116//****************************************************************************
117// windows
118
119#ifdef WIN32
120
121// isn't cygwin annoying!
122#ifdef CYGWIN
123#define _snprintf snprintf
124#define _vsnprintf vsnprintf
125#endif
126
127
128#include "windows.h"
129
130
131extern "C" void dError (int num, const char *msg, ...)
132{
133 va_list ap;
134 va_start (ap,msg);
135 if (error_function) error_function (num,msg,ap);
136 else {
137 char s[1000],title[100];
138 _snprintf (title,sizeof(title),"ODE Error %d",num);
139 _vsnprintf (s,sizeof(s),msg,ap);
140 s[sizeof(s)-1] = 0;
141 MessageBox(0,s,title,MB_OK | MB_ICONWARNING);
142 }
143 exit (1);
144}
145
146
147extern "C" void dDebug (int num, const char *msg, ...)
148{
149 va_list ap;
150 va_start (ap,msg);
151 if (debug_function) debug_function (num,msg,ap);
152 else {
153 char s[1000],title[100];
154 _snprintf (title,sizeof(title),"ODE INTERNAL ERROR %d",num);
155 _vsnprintf (s,sizeof(s),msg,ap);
156 s[sizeof(s)-1] = 0;
157 MessageBox(0,s,title,MB_OK | MB_ICONSTOP);
158 }
159 abort();
160}
161
162
163extern "C" void dMessage (int num, const char *msg, ...)
164{
165 va_list ap;
166 va_start (ap,msg);
167 if (message_function) message_function (num,msg,ap);
168 else printMessage (num,"ODE Message",msg,ap);
169}
170
171
172#endif
diff --git a/libraries/ode-0.9/ode/src/export-dif.cpp b/libraries/ode-0.9/ode/src/export-dif.cpp
deleted file mode 100644
index 577d3e1..0000000
--- a/libraries/ode-0.9/ode/src/export-dif.cpp
+++ /dev/null
@@ -1,568 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24 * Export a DIF (Dynamics Interchange Format) file.
25 */
26
27
28// @@@ TODO:
29// * export all spaces, and geoms in spaces, not just ones attached to bodies
30// (separate export function?)
31// * say the space each geom is in, so reader can construct space heirarchy
32// * limot --> separate out into limits and motors?
33// * make sure ODE-specific parameters divided out
34
35
36#include "ode/ode.h"
37#include "objects.h"
38#include "joint.h"
39#include "collision_kernel.h"
40
41//***************************************************************************
42// utility
43
44struct PrintingContext {
45 FILE *file; // file to write to
46 int precision; // digits of precision to print
47 int indent; // number of levels of indent
48
49 void printIndent();
50 void printReal (dReal x);
51 void print (const char *name, int x);
52 void print (const char *name, dReal x);
53 void print (const char *name, const dReal *x, int n=3);
54 void print (const char *name, const char *x=0);
55 void printNonzero (const char *name, dReal x);
56 void printNonzero (const char *name, const dReal x[3]);
57};
58
59
60void PrintingContext::printIndent()
61{
62 for (int i=0; i<indent; i++) fputc ('\t',file);
63}
64
65
66void PrintingContext::print (const char *name, int x)
67{
68 printIndent();
69 fprintf (file,"%s = %d,\n",name,x);
70}
71
72
73void PrintingContext::printReal (dReal x)
74{
75 if (x==dInfinity) {
76 fprintf (file,"inf");
77 }
78 else if (x==-dInfinity) {
79 fprintf (file,"-inf");
80 }
81 else {
82 fprintf (file,"%.*g",precision,x);
83 }
84}
85
86
87void PrintingContext::print (const char *name, dReal x)
88{
89 printIndent();
90 fprintf (file,"%s = ",name);
91 printReal (x);
92 fprintf (file,",\n");
93}
94
95
96void PrintingContext::print (const char *name, const dReal *x, int n)
97{
98 printIndent();
99 fprintf (file,"%s = {",name);
100 for (int i=0; i<n; i++) {
101 printReal (x[i]);
102 if (i < n-1) fputc (',',file);
103 }
104 fprintf (file,"},\n");
105}
106
107
108void PrintingContext::print (const char *name, const char *x)
109{
110 printIndent();
111 if (x) {
112 fprintf (file,"%s = \"%s\",\n",name,x);
113 }
114 else {
115 fprintf (file,"%s\n",name);
116 }
117}
118
119
120void PrintingContext::printNonzero (const char *name, dReal x)
121{
122 if (x != 0) print (name,x);
123}
124
125
126void PrintingContext::printNonzero (const char *name, const dReal x[3])
127{
128 if (x[0] != 0 && x[1] != 0 && x[2] != 0) print (name,x);
129}
130
131//***************************************************************************
132// joints
133
134
135static void printLimot (PrintingContext &c, dxJointLimitMotor &limot, int num)
136{
137 if (num >= 0) {
138 c.printIndent();
139 fprintf (c.file,"limit%d = {\n",num);
140 }
141 else {
142 c.print ("limit = {");
143 }
144 c.indent++;
145 c.print ("low_stop",limot.lostop);
146 c.print ("high_stop",limot.histop);
147 c.printNonzero ("bounce",limot.bounce);
148 c.print ("ODE = {");
149 c.indent++;
150 c.printNonzero ("stop_erp",limot.stop_erp);
151 c.printNonzero ("stop_cfm",limot.stop_cfm);
152 c.indent--;
153 c.print ("},");
154 c.indent--;
155 c.print ("},");
156
157 if (num >= 0) {
158 c.printIndent();
159 fprintf (c.file,"motor%d = {\n",num);
160 }
161 else {
162 c.print ("motor = {");
163 }
164 c.indent++;
165 c.printNonzero ("vel",limot.vel);
166 c.printNonzero ("fmax",limot.fmax);
167 c.print ("ODE = {");
168 c.indent++;
169 c.printNonzero ("fudge_factor",limot.fudge_factor);
170 c.printNonzero ("normal_cfm",limot.normal_cfm);
171 c.indent--;
172 c.print ("},");
173 c.indent--;
174 c.print ("},");
175}
176
177
178static const char *getJointName (dxJoint *j)
179{
180 switch (j->vtable->typenum) {
181 case dJointTypeBall: return "ball";
182 case dJointTypeHinge: return "hinge";
183 case dJointTypeSlider: return "slider";
184 case dJointTypeContact: return "contact";
185 case dJointTypeUniversal: return "universal";
186 case dJointTypeHinge2: return "ODE_hinge2";
187 case dJointTypeFixed: return "fixed";
188 case dJointTypeNull: return "null";
189 case dJointTypeAMotor: return "ODE_angular_motor";
190 case dJointTypeLMotor: return "ODE_linear_motor";
191 case dJointTypePR: return "PR";
192 }
193 return "unknown";
194}
195
196
197static void printBall (PrintingContext &c, dxJoint *j)
198{
199 dxJointBall *b = (dxJointBall*) j;
200 c.print ("anchor1",b->anchor1);
201 c.print ("anchor2",b->anchor2);
202}
203
204
205static void printHinge (PrintingContext &c, dxJoint *j)
206{
207 dxJointHinge *h = (dxJointHinge*) j;
208 c.print ("anchor1",h->anchor1);
209 c.print ("anchor2",h->anchor2);
210 c.print ("axis1",h->axis1);
211 c.print ("axis2",h->axis2);
212 c.print ("qrel",h->qrel,4);
213 printLimot (c,h->limot,-1);
214}
215
216
217static void printSlider (PrintingContext &c, dxJoint *j)
218{
219 dxJointSlider *s = (dxJointSlider*) j;
220 c.print ("axis1",s->axis1);
221 c.print ("qrel",s->qrel,4);
222 c.print ("offset",s->offset);
223 printLimot (c,s->limot,-1);
224}
225
226
227static void printContact (PrintingContext &c, dxJoint *j)
228{
229 dxJointContact *ct = (dxJointContact*) j;
230 int mode = ct->contact.surface.mode;
231 c.print ("pos",ct->contact.geom.pos);
232 c.print ("normal",ct->contact.geom.normal);
233 c.print ("depth",ct->contact.geom.depth);
234 //@@@ may want to write the geoms g1 and g2 that are involved, for debugging.
235 // to do this we must have written out all geoms in all spaces, not just
236 // geoms that are attached to bodies.
237 c.print ("mu",ct->contact.surface.mu);
238 if (mode & dContactMu2) c.print ("mu2",ct->contact.surface.mu2);
239 if (mode & dContactBounce) c.print ("bounce",ct->contact.surface.bounce);
240 if (mode & dContactBounce) c.print ("bounce_vel",ct->contact.surface.bounce_vel);
241 if (mode & dContactSoftERP) c.print ("soft_ERP",ct->contact.surface.soft_erp);
242 if (mode & dContactSoftCFM) c.print ("soft_CFM",ct->contact.surface.soft_cfm);
243 if (mode & dContactMotion1) c.print ("motion1",ct->contact.surface.motion1);
244 if (mode & dContactMotion2) c.print ("motion2",ct->contact.surface.motion2);
245 if (mode & dContactSlip1) c.print ("slip1",ct->contact.surface.slip1);
246 if (mode & dContactSlip2) c.print ("slip2",ct->contact.surface.slip2);
247 int fa = 0; // friction approximation code
248 if (mode & dContactApprox1_1) fa |= 1;
249 if (mode & dContactApprox1_2) fa |= 2;
250 if (fa) c.print ("friction_approximation",fa);
251 if (mode & dContactFDir1) c.print ("fdir1",ct->contact.fdir1);
252}
253
254
255static void printUniversal (PrintingContext &c, dxJoint *j)
256{
257 dxJointUniversal *u = (dxJointUniversal*) j;
258 c.print ("anchor1",u->anchor1);
259 c.print ("anchor2",u->anchor2);
260 c.print ("axis1",u->axis1);
261 c.print ("axis2",u->axis2);
262 c.print ("qrel1",u->qrel1,4);
263 c.print ("qrel2",u->qrel2,4);
264 printLimot (c,u->limot1,1);
265 printLimot (c,u->limot2,2);
266}
267
268
269static void printHinge2 (PrintingContext &c, dxJoint *j)
270{
271 dxJointHinge2 *h = (dxJointHinge2*) j;
272 c.print ("anchor1",h->anchor1);
273 c.print ("anchor2",h->anchor2);
274 c.print ("axis1",h->axis1);
275 c.print ("axis2",h->axis2);
276 c.print ("v1",h->v1); //@@@ much better to write out 'qrel' here, if it's available
277 c.print ("v2",h->v2);
278 c.print ("susp_erp",h->susp_erp);
279 c.print ("susp_cfm",h->susp_cfm);
280 printLimot (c,h->limot1,1);
281 printLimot (c,h->limot2,2);
282}
283
284static void printPR (PrintingContext &c, dxJoint *j)
285{
286 dxJointPR *pr = (dxJointPR*) j;
287 c.print ("anchor2",pr->anchor2);
288 c.print ("axisR1",pr->axisR1);
289 c.print ("axisR2",pr->axisR2);
290 c.print ("axisP1",pr->axisP1);
291 c.print ("qrel",pr->qrel,4);
292 c.print ("offset",pr->offset);
293 printLimot (c,pr->limotP,1);
294 printLimot (c,pr->limotR,2);
295}
296
297
298static void printFixed (PrintingContext &c, dxJoint *j)
299{
300 dxJointFixed *f = (dxJointFixed*) j;
301 c.print ("qrel",f->qrel);
302 c.print ("offset",f->offset);
303}
304
305static void printLMotor (PrintingContext &c, dxJoint *j)
306{
307 dxJointLMotor *a = (dxJointLMotor*) j;
308 c.print("num", a->num);
309 c.printIndent();
310 fprintf (c.file,"rel = {%d,%d,%d},\n",a->rel[0],a->rel[1],a->rel[2]);
311 c.print ("axis1",a->axis[0]);
312 c.print ("axis2",a->axis[1]);
313 c.print ("axis3",a->axis[2]);
314 for (int i=0; i<3; i++) printLimot (c,a->limot[i],i+1);
315}
316
317
318static void printAMotor (PrintingContext &c, dxJoint *j)
319{
320 dxJointAMotor *a = (dxJointAMotor*) j;
321 c.print ("num",a->num);
322 c.print ("mode",a->mode);
323 c.printIndent();
324 fprintf (c.file,"rel = {%d,%d,%d},\n",a->rel[0],a->rel[1],a->rel[2]);
325 c.print ("axis1",a->axis[0]);
326 c.print ("axis2",a->axis[1]);
327 c.print ("axis3",a->axis[2]);
328 for (int i=0; i<3; i++) printLimot (c,a->limot[i],i+1);
329 c.print ("angle1",a->angle[0]);
330 c.print ("angle2",a->angle[1]);
331 c.print ("angle3",a->angle[2]);
332}
333
334//***************************************************************************
335// geometry
336
337static void printGeom (PrintingContext &c, dxGeom *g);
338
339static void printSphere (PrintingContext &c, dxGeom *g)
340{
341 c.print ("type","sphere");
342 c.print ("radius",dGeomSphereGetRadius (g));
343}
344
345
346static void printBox (PrintingContext &c, dxGeom *g)
347{
348 dVector3 sides;
349 dGeomBoxGetLengths (g,sides);
350 c.print ("type","box");
351 c.print ("sides",sides);
352}
353
354
355
356static void printCapsule (PrintingContext &c, dxGeom *g)
357{
358 dReal radius,length;
359 dGeomCapsuleGetParams (g,&radius,&length);
360 c.print ("type","capsule");
361 c.print ("radius",radius);
362 c.print ("length",length);
363}
364
365
366static void printPlane (PrintingContext &c, dxGeom *g)
367{
368 dVector4 e;
369 dGeomPlaneGetParams (g,e);
370 c.print ("type","plane");
371 c.print ("normal",e);
372 c.print ("d",e[3]);
373}
374
375
376
377static void printRay (PrintingContext &c, dxGeom *g)
378{
379 dReal length = dGeomRayGetLength (g);
380 c.print ("type","ray");
381 c.print ("length",length);
382}
383
384
385
386static void printGeomTransform (PrintingContext &c, dxGeom *g)
387{
388 dxGeom *g2 = dGeomTransformGetGeom (g);
389 const dReal *pos = dGeomGetPosition (g2);
390 dQuaternion q;
391 dGeomGetQuaternion (g2,q);
392 c.print ("type","transform");
393 c.print ("pos",pos);
394 c.print ("q",q,4);
395 c.print ("geometry = {");
396 c.indent++;
397 printGeom (c,g2);
398 c.indent--;
399 c.print ("}");
400}
401
402
403
404static void printTriMesh (PrintingContext &c, dxGeom *g)
405{
406 c.print ("type","trimesh");
407 //@@@ i don't think that the trimesh accessor functions are really
408 // sufficient to read out all the triangle data, and anyway we
409 // should have a method of not duplicating trimesh data that is
410 // shared.
411}
412
413
414static void printGeom (PrintingContext &c, dxGeom *g)
415{
416 unsigned long category = dGeomGetCategoryBits (g);
417 if (category != (unsigned long)(~0)) {
418 c.printIndent();
419 fprintf (c.file,"category_bits = %lu\n",category);
420 }
421 unsigned long collide = dGeomGetCollideBits (g);
422 if (collide != (unsigned long)(~0)) {
423 c.printIndent();
424 fprintf (c.file,"collide_bits = %lu\n",collide);
425 }
426 if (!dGeomIsEnabled (g)) {
427 c.print ("disabled",1);
428 }
429 switch (g->type) {
430 case dSphereClass: printSphere (c,g); break;
431 case dBoxClass: printBox (c,g); break;
432 case dCapsuleClass: printCapsule (c,g); break;
433 case dPlaneClass: printPlane (c,g); break;
434 case dRayClass: printRay (c,g); break;
435 case dGeomTransformClass: printGeomTransform (c,g); break;
436 case dTriMeshClass: printTriMesh (c,g); break;
437 }
438}
439
440//***************************************************************************
441// world
442
443void dWorldExportDIF (dWorldID w, FILE *file, const char *prefix)
444{
445 PrintingContext c;
446 c.file = file;
447#if defined(dSINGLE)
448 c.precision = 7;
449#else
450 c.precision = 15;
451#endif
452 c.indent = 1;
453
454 fprintf (file,"-- Dynamics Interchange Format v0.1\n\n%sworld = dynamics.world {\n",prefix);
455 c.print ("gravity",w->gravity);
456 c.print ("ODE = {");
457 c.indent++;
458 c.print ("ERP",w->global_erp);
459 c.print ("CFM",w->global_cfm);
460 c.print ("auto_disable = {");
461 c.indent++;
462 c.print ("linear_threshold",w->adis.linear_average_threshold);
463 c.print ("angular_threshold",w->adis.angular_average_threshold);
464 c.print ("average_samples",(int)w->adis.average_samples);
465 c.print ("idle_time",w->adis.idle_time);
466 c.print ("idle_steps",w->adis.idle_steps);
467 fprintf (file,"\t\t},\n\t},\n}\n");
468 c.indent -= 3;
469
470 // bodies
471 int num = 0;
472 fprintf (file,"%sbody = {}\n",prefix);
473 for (dxBody *b=w->firstbody; b; b=(dxBody*)b->next) {
474 b->tag = num;
475 fprintf (file,"%sbody[%d] = dynamics.body {\n\tworld = %sworld,\n",prefix,num,prefix);
476 c.indent++;
477 c.print ("pos",b->posr.pos);
478 c.print ("q",b->q,4);
479 c.print ("lvel",b->lvel);
480 c.print ("avel",b->avel);
481 c.print ("mass",b->mass.mass);
482 fprintf (file,"\tI = {{");
483 for (int i=0; i<3; i++) {
484 for (int j=0; j<3; j++) {
485 c.printReal (b->mass.I[i*4+j]);
486 if (j < 2) fputc (',',file);
487 }
488 if (i < 2) fprintf (file,"},{");
489 }
490 fprintf (file,"}},\n");
491 c.printNonzero ("com",b->mass.c);
492 c.print ("ODE = {");
493 c.indent++;
494 if (b->flags & dxBodyFlagFiniteRotation) c.print ("finite_rotation",1);
495 if (b->flags & dxBodyDisabled) c.print ("disabled",1);
496 if (b->flags & dxBodyNoGravity) c.print ("no_gravity",1);
497 if (b->flags & dxBodyAutoDisable) {
498 c.print ("auto_disable = {");
499 c.indent++;
500 c.print ("linear_threshold",b->adis.linear_average_threshold);
501 c.print ("angular_threshold",b->adis.angular_average_threshold);
502 c.print ("average_samples",(int)b->adis.average_samples);
503 c.print ("idle_time",b->adis.idle_time);
504 c.print ("idle_steps",b->adis.idle_steps);
505 c.print ("time_left",b->adis_timeleft);
506 c.print ("steps_left",b->adis_stepsleft);
507 c.indent--;
508 c.print ("},");
509 }
510 c.printNonzero ("facc",b->facc);
511 c.printNonzero ("tacc",b->tacc);
512 if (b->flags & dxBodyFlagFiniteRotationAxis) {
513 c.print ("finite_rotation_axis",b->finite_rot_axis);
514 }
515 c.indent--;
516 c.print ("},");
517 if (b->geom) {
518 c.print ("geometry = {");
519 c.indent++;
520 for (dxGeom *g=b->geom; g; g=g->body_next) {
521 c.print ("{");
522 c.indent++;
523 printGeom (c,g);
524 c.indent--;
525 c.print ("},");
526 }
527 c.indent--;
528 c.print ("},");
529 }
530 c.indent--;
531 c.print ("}");
532 num++;
533 }
534
535 // joints
536 num = 0;
537 fprintf (file,"%sjoint = {}\n",prefix);
538 for (dxJoint *j=w->firstjoint; j; j=(dxJoint*)j->next) {
539 c.indent++;
540 const char *name = getJointName (j);
541 fprintf (file,
542 "%sjoint[%d] = dynamics.%s_joint {\n"
543 "\tworld = %sworld,\n"
544 "\tbody = {"
545 ,prefix,num,name,prefix);
546
547 if ( j->node[0].body )
548 fprintf (file,"%sbody[%d]",prefix,j->node[0].body->tag);
549 if ( j->node[1].body )
550 fprintf (file,",%sbody[%d]",prefix,j->node[1].body->tag);
551
552 switch (j->vtable->typenum) {
553 case dJointTypeBall: printBall (c,j); break;
554 case dJointTypeHinge: printHinge (c,j); break;
555 case dJointTypeSlider: printSlider (c,j); break;
556 case dJointTypeContact: printContact (c,j); break;
557 case dJointTypeUniversal: printUniversal (c,j); break;
558 case dJointTypeHinge2: printHinge2 (c,j); break;
559 case dJointTypeFixed: printFixed (c,j); break;
560 case dJointTypeAMotor: printAMotor (c,j); break;
561 case dJointTypeLMotor: printLMotor (c,j); break;
562 case dJointTypePR: printPR (c,j); break;
563 }
564 c.indent--;
565 c.print ("}");
566 num++;
567 }
568}
diff --git a/libraries/ode-0.9/ode/src/fastdot.c b/libraries/ode-0.9/ode/src/fastdot.c
deleted file mode 100644
index 148d2dd..0000000
--- a/libraries/ode-0.9/ode/src/fastdot.c
+++ /dev/null
@@ -1,30 +0,0 @@
1/* generated code, do not edit. */
2
3#include "ode/matrix.h"
4
5
6dReal dDot (const dReal *a, const dReal *b, int n)
7{
8 dReal p0,q0,m0,p1,q1,m1,sum;
9 sum = 0;
10 n -= 2;
11 while (n >= 0) {
12 p0 = a[0]; q0 = b[0];
13 m0 = p0 * q0;
14 p1 = a[1]; q1 = b[1];
15 m1 = p1 * q1;
16 sum += m0;
17 sum += m1;
18 a += 2;
19 b += 2;
20 n -= 2;
21 }
22 n += 2;
23 while (n > 0) {
24 sum += (*a) * (*b);
25 a++;
26 b++;
27 n--;
28 }
29 return sum;
30}
diff --git a/libraries/ode-0.9/ode/src/fastldlt.c b/libraries/ode-0.9/ode/src/fastldlt.c
deleted file mode 100644
index df2ea6e..0000000
--- a/libraries/ode-0.9/ode/src/fastldlt.c
+++ /dev/null
@@ -1,381 +0,0 @@
1/* generated code, do not edit. */
2
3#include "ode/matrix.h"
4
5/* solve L*X=B, with B containing 1 right hand sides.
6 * L is an n*n lower triangular matrix with ones on the diagonal.
7 * L is stored by rows and its leading dimension is lskip.
8 * B is an n*1 matrix that contains the right hand sides.
9 * B is stored by columns and its leading dimension is also lskip.
10 * B is overwritten with X.
11 * this processes blocks of 2*2.
12 * if this is in the factorizer source file, n must be a multiple of 2.
13 */
14
15static void dSolveL1_1 (const dReal *L, dReal *B, int n, int lskip1)
16{
17 /* declare variables - Z matrix, p and q vectors, etc */
18 dReal Z11,m11,Z21,m21,p1,q1,p2,*ex;
19 const dReal *ell;
20 int i,j;
21 /* compute all 2 x 1 blocks of X */
22 for (i=0; i < n; i+=2) {
23 /* compute all 2 x 1 block of X, from rows i..i+2-1 */
24 /* set the Z matrix to 0 */
25 Z11=0;
26 Z21=0;
27 ell = L + i*lskip1;
28 ex = B;
29 /* the inner loop that computes outer products and adds them to Z */
30 for (j=i-2; j >= 0; j -= 2) {
31 /* compute outer product and add it to the Z matrix */
32 p1=ell[0];
33 q1=ex[0];
34 m11 = p1 * q1;
35 p2=ell[lskip1];
36 m21 = p2 * q1;
37 Z11 += m11;
38 Z21 += m21;
39 /* compute outer product and add it to the Z matrix */
40 p1=ell[1];
41 q1=ex[1];
42 m11 = p1 * q1;
43 p2=ell[1+lskip1];
44 m21 = p2 * q1;
45 /* advance pointers */
46 ell += 2;
47 ex += 2;
48 Z11 += m11;
49 Z21 += m21;
50 /* end of inner loop */
51 }
52 /* compute left-over iterations */
53 j += 2;
54 for (; j > 0; j--) {
55 /* compute outer product and add it to the Z matrix */
56 p1=ell[0];
57 q1=ex[0];
58 m11 = p1 * q1;
59 p2=ell[lskip1];
60 m21 = p2 * q1;
61 /* advance pointers */
62 ell += 1;
63 ex += 1;
64 Z11 += m11;
65 Z21 += m21;
66 }
67 /* finish computing the X(i) block */
68 Z11 = ex[0] - Z11;
69 ex[0] = Z11;
70 p1 = ell[lskip1];
71 Z21 = ex[1] - Z21 - p1*Z11;
72 ex[1] = Z21;
73 /* end of outer loop */
74 }
75}
76
77/* solve L*X=B, with B containing 2 right hand sides.
78 * L is an n*n lower triangular matrix with ones on the diagonal.
79 * L is stored by rows and its leading dimension is lskip.
80 * B is an n*2 matrix that contains the right hand sides.
81 * B is stored by columns and its leading dimension is also lskip.
82 * B is overwritten with X.
83 * this processes blocks of 2*2.
84 * if this is in the factorizer source file, n must be a multiple of 2.
85 */
86
87static void dSolveL1_2 (const dReal *L, dReal *B, int n, int lskip1)
88{
89 /* declare variables - Z matrix, p and q vectors, etc */
90 dReal Z11,m11,Z12,m12,Z21,m21,Z22,m22,p1,q1,p2,q2,*ex;
91 const dReal *ell;
92 int i,j;
93 /* compute all 2 x 2 blocks of X */
94 for (i=0; i < n; i+=2) {
95 /* compute all 2 x 2 block of X, from rows i..i+2-1 */
96 /* set the Z matrix to 0 */
97 Z11=0;
98 Z12=0;
99 Z21=0;
100 Z22=0;
101 ell = L + i*lskip1;
102 ex = B;
103 /* the inner loop that computes outer products and adds them to Z */
104 for (j=i-2; j >= 0; j -= 2) {
105 /* compute outer product and add it to the Z matrix */
106 p1=ell[0];
107 q1=ex[0];
108 m11 = p1 * q1;
109 q2=ex[lskip1];
110 m12 = p1 * q2;
111 p2=ell[lskip1];
112 m21 = p2 * q1;
113 m22 = p2 * q2;
114 Z11 += m11;
115 Z12 += m12;
116 Z21 += m21;
117 Z22 += m22;
118 /* compute outer product and add it to the Z matrix */
119 p1=ell[1];
120 q1=ex[1];
121 m11 = p1 * q1;
122 q2=ex[1+lskip1];
123 m12 = p1 * q2;
124 p2=ell[1+lskip1];
125 m21 = p2 * q1;
126 m22 = p2 * q2;
127 /* advance pointers */
128 ell += 2;
129 ex += 2;
130 Z11 += m11;
131 Z12 += m12;
132 Z21 += m21;
133 Z22 += m22;
134 /* end of inner loop */
135 }
136 /* compute left-over iterations */
137 j += 2;
138 for (; j > 0; j--) {
139 /* compute outer product and add it to the Z matrix */
140 p1=ell[0];
141 q1=ex[0];
142 m11 = p1 * q1;
143 q2=ex[lskip1];
144 m12 = p1 * q2;
145 p2=ell[lskip1];
146 m21 = p2 * q1;
147 m22 = p2 * q2;
148 /* advance pointers */
149 ell += 1;
150 ex += 1;
151 Z11 += m11;
152 Z12 += m12;
153 Z21 += m21;
154 Z22 += m22;
155 }
156 /* finish computing the X(i) block */
157 Z11 = ex[0] - Z11;
158 ex[0] = Z11;
159 Z12 = ex[lskip1] - Z12;
160 ex[lskip1] = Z12;
161 p1 = ell[lskip1];
162 Z21 = ex[1] - Z21 - p1*Z11;
163 ex[1] = Z21;
164 Z22 = ex[1+lskip1] - Z22 - p1*Z12;
165 ex[1+lskip1] = Z22;
166 /* end of outer loop */
167 }
168}
169
170
171void dFactorLDLT (dReal *A, dReal *d, int n, int nskip1)
172{
173 int i,j;
174 dReal sum,*ell,*dee,dd,p1,p2,q1,q2,Z11,m11,Z21,m21,Z22,m22;
175 if (n < 1) return;
176
177 for (i=0; i<=n-2; i += 2) {
178 /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
179 dSolveL1_2 (A,A+i*nskip1,i,nskip1);
180 /* scale the elements in a 2 x i block at A(i,0), and also */
181 /* compute Z = the outer product matrix that we'll need. */
182 Z11 = 0;
183 Z21 = 0;
184 Z22 = 0;
185 ell = A+i*nskip1;
186 dee = d;
187 for (j=i-6; j >= 0; j -= 6) {
188 p1 = ell[0];
189 p2 = ell[nskip1];
190 dd = dee[0];
191 q1 = p1*dd;
192 q2 = p2*dd;
193 ell[0] = q1;
194 ell[nskip1] = q2;
195 m11 = p1*q1;
196 m21 = p2*q1;
197 m22 = p2*q2;
198 Z11 += m11;
199 Z21 += m21;
200 Z22 += m22;
201 p1 = ell[1];
202 p2 = ell[1+nskip1];
203 dd = dee[1];
204 q1 = p1*dd;
205 q2 = p2*dd;
206 ell[1] = q1;
207 ell[1+nskip1] = q2;
208 m11 = p1*q1;
209 m21 = p2*q1;
210 m22 = p2*q2;
211 Z11 += m11;
212 Z21 += m21;
213 Z22 += m22;
214 p1 = ell[2];
215 p2 = ell[2+nskip1];
216 dd = dee[2];
217 q1 = p1*dd;
218 q2 = p2*dd;
219 ell[2] = q1;
220 ell[2+nskip1] = q2;
221 m11 = p1*q1;
222 m21 = p2*q1;
223 m22 = p2*q2;
224 Z11 += m11;
225 Z21 += m21;
226 Z22 += m22;
227 p1 = ell[3];
228 p2 = ell[3+nskip1];
229 dd = dee[3];
230 q1 = p1*dd;
231 q2 = p2*dd;
232 ell[3] = q1;
233 ell[3+nskip1] = q2;
234 m11 = p1*q1;
235 m21 = p2*q1;
236 m22 = p2*q2;
237 Z11 += m11;
238 Z21 += m21;
239 Z22 += m22;
240 p1 = ell[4];
241 p2 = ell[4+nskip1];
242 dd = dee[4];
243 q1 = p1*dd;
244 q2 = p2*dd;
245 ell[4] = q1;
246 ell[4+nskip1] = q2;
247 m11 = p1*q1;
248 m21 = p2*q1;
249 m22 = p2*q2;
250 Z11 += m11;
251 Z21 += m21;
252 Z22 += m22;
253 p1 = ell[5];
254 p2 = ell[5+nskip1];
255 dd = dee[5];
256 q1 = p1*dd;
257 q2 = p2*dd;
258 ell[5] = q1;
259 ell[5+nskip1] = q2;
260 m11 = p1*q1;
261 m21 = p2*q1;
262 m22 = p2*q2;
263 Z11 += m11;
264 Z21 += m21;
265 Z22 += m22;
266 ell += 6;
267 dee += 6;
268 }
269 /* compute left-over iterations */
270 j += 6;
271 for (; j > 0; j--) {
272 p1 = ell[0];
273 p2 = ell[nskip1];
274 dd = dee[0];
275 q1 = p1*dd;
276 q2 = p2*dd;
277 ell[0] = q1;
278 ell[nskip1] = q2;
279 m11 = p1*q1;
280 m21 = p2*q1;
281 m22 = p2*q2;
282 Z11 += m11;
283 Z21 += m21;
284 Z22 += m22;
285 ell++;
286 dee++;
287 }
288 /* solve for diagonal 2 x 2 block at A(i,i) */
289 Z11 = ell[0] - Z11;
290 Z21 = ell[nskip1] - Z21;
291 Z22 = ell[1+nskip1] - Z22;
292 dee = d + i;
293 /* factorize 2 x 2 block Z,dee */
294 /* factorize row 1 */
295 dee[0] = dRecip(Z11);
296 /* factorize row 2 */
297 sum = 0;
298 q1 = Z21;
299 q2 = q1 * dee[0];
300 Z21 = q2;
301 sum += q1*q2;
302 dee[1] = dRecip(Z22 - sum);
303 /* done factorizing 2 x 2 block */
304 ell[nskip1] = Z21;
305 }
306 /* compute the (less than 2) rows at the bottom */
307 switch (n-i) {
308 case 0:
309 break;
310
311 case 1:
312 dSolveL1_1 (A,A+i*nskip1,i,nskip1);
313 /* scale the elements in a 1 x i block at A(i,0), and also */
314 /* compute Z = the outer product matrix that we'll need. */
315 Z11 = 0;
316 ell = A+i*nskip1;
317 dee = d;
318 for (j=i-6; j >= 0; j -= 6) {
319 p1 = ell[0];
320 dd = dee[0];
321 q1 = p1*dd;
322 ell[0] = q1;
323 m11 = p1*q1;
324 Z11 += m11;
325 p1 = ell[1];
326 dd = dee[1];
327 q1 = p1*dd;
328 ell[1] = q1;
329 m11 = p1*q1;
330 Z11 += m11;
331 p1 = ell[2];
332 dd = dee[2];
333 q1 = p1*dd;
334 ell[2] = q1;
335 m11 = p1*q1;
336 Z11 += m11;
337 p1 = ell[3];
338 dd = dee[3];
339 q1 = p1*dd;
340 ell[3] = q1;
341 m11 = p1*q1;
342 Z11 += m11;
343 p1 = ell[4];
344 dd = dee[4];
345 q1 = p1*dd;
346 ell[4] = q1;
347 m11 = p1*q1;
348 Z11 += m11;
349 p1 = ell[5];
350 dd = dee[5];
351 q1 = p1*dd;
352 ell[5] = q1;
353 m11 = p1*q1;
354 Z11 += m11;
355 ell += 6;
356 dee += 6;
357 }
358 /* compute left-over iterations */
359 j += 6;
360 for (; j > 0; j--) {
361 p1 = ell[0];
362 dd = dee[0];
363 q1 = p1*dd;
364 ell[0] = q1;
365 m11 = p1*q1;
366 Z11 += m11;
367 ell++;
368 dee++;
369 }
370 /* solve for diagonal 1 x 1 block at A(i,i) */
371 Z11 = ell[0] - Z11;
372 dee = d + i;
373 /* factorize 1 x 1 block Z,dee */
374 /* factorize row 1 */
375 dee[0] = dRecip(Z11);
376 /* done factorizing 1 x 1 block */
377 break;
378
379 default: *((char*)0)=0; /* this should never happen! */
380 }
381}
diff --git a/libraries/ode-0.9/ode/src/fastlsolve.c b/libraries/ode-0.9/ode/src/fastlsolve.c
deleted file mode 100644
index 0ae99d6..0000000
--- a/libraries/ode-0.9/ode/src/fastlsolve.c
+++ /dev/null
@@ -1,298 +0,0 @@
1/* generated code, do not edit. */
2
3#include "ode/matrix.h"
4
5/* solve L*X=B, with B containing 1 right hand sides.
6 * L is an n*n lower triangular matrix with ones on the diagonal.
7 * L is stored by rows and its leading dimension is lskip.
8 * B is an n*1 matrix that contains the right hand sides.
9 * B is stored by columns and its leading dimension is also lskip.
10 * B is overwritten with X.
11 * this processes blocks of 4*4.
12 * if this is in the factorizer source file, n must be a multiple of 4.
13 */
14
15void dSolveL1 (const dReal *L, dReal *B, int n, int lskip1)
16{
17 /* declare variables - Z matrix, p and q vectors, etc */
18 dReal Z11,Z21,Z31,Z41,p1,q1,p2,p3,p4,*ex;
19 const dReal *ell;
20 int lskip2,lskip3,i,j;
21 /* compute lskip values */
22 lskip2 = 2*lskip1;
23 lskip3 = 3*lskip1;
24 /* compute all 4 x 1 blocks of X */
25 for (i=0; i <= n-4; i+=4) {
26 /* compute all 4 x 1 block of X, from rows i..i+4-1 */
27 /* set the Z matrix to 0 */
28 Z11=0;
29 Z21=0;
30 Z31=0;
31 Z41=0;
32 ell = L + i*lskip1;
33 ex = B;
34 /* the inner loop that computes outer products and adds them to Z */
35 for (j=i-12; j >= 0; j -= 12) {
36 /* load p and q values */
37 p1=ell[0];
38 q1=ex[0];
39 p2=ell[lskip1];
40 p3=ell[lskip2];
41 p4=ell[lskip3];
42 /* compute outer product and add it to the Z matrix */
43 Z11 += p1 * q1;
44 Z21 += p2 * q1;
45 Z31 += p3 * q1;
46 Z41 += p4 * q1;
47 /* load p and q values */
48 p1=ell[1];
49 q1=ex[1];
50 p2=ell[1+lskip1];
51 p3=ell[1+lskip2];
52 p4=ell[1+lskip3];
53 /* compute outer product and add it to the Z matrix */
54 Z11 += p1 * q1;
55 Z21 += p2 * q1;
56 Z31 += p3 * q1;
57 Z41 += p4 * q1;
58 /* load p and q values */
59 p1=ell[2];
60 q1=ex[2];
61 p2=ell[2+lskip1];
62 p3=ell[2+lskip2];
63 p4=ell[2+lskip3];
64 /* compute outer product and add it to the Z matrix */
65 Z11 += p1 * q1;
66 Z21 += p2 * q1;
67 Z31 += p3 * q1;
68 Z41 += p4 * q1;
69 /* load p and q values */
70 p1=ell[3];
71 q1=ex[3];
72 p2=ell[3+lskip1];
73 p3=ell[3+lskip2];
74 p4=ell[3+lskip3];
75 /* compute outer product and add it to the Z matrix */
76 Z11 += p1 * q1;
77 Z21 += p2 * q1;
78 Z31 += p3 * q1;
79 Z41 += p4 * q1;
80 /* load p and q values */
81 p1=ell[4];
82 q1=ex[4];
83 p2=ell[4+lskip1];
84 p3=ell[4+lskip2];
85 p4=ell[4+lskip3];
86 /* compute outer product and add it to the Z matrix */
87 Z11 += p1 * q1;
88 Z21 += p2 * q1;
89 Z31 += p3 * q1;
90 Z41 += p4 * q1;
91 /* load p and q values */
92 p1=ell[5];
93 q1=ex[5];
94 p2=ell[5+lskip1];
95 p3=ell[5+lskip2];
96 p4=ell[5+lskip3];
97 /* compute outer product and add it to the Z matrix */
98 Z11 += p1 * q1;
99 Z21 += p2 * q1;
100 Z31 += p3 * q1;
101 Z41 += p4 * q1;
102 /* load p and q values */
103 p1=ell[6];
104 q1=ex[6];
105 p2=ell[6+lskip1];
106 p3=ell[6+lskip2];
107 p4=ell[6+lskip3];
108 /* compute outer product and add it to the Z matrix */
109 Z11 += p1 * q1;
110 Z21 += p2 * q1;
111 Z31 += p3 * q1;
112 Z41 += p4 * q1;
113 /* load p and q values */
114 p1=ell[7];
115 q1=ex[7];
116 p2=ell[7+lskip1];
117 p3=ell[7+lskip2];
118 p4=ell[7+lskip3];
119 /* compute outer product and add it to the Z matrix */
120 Z11 += p1 * q1;
121 Z21 += p2 * q1;
122 Z31 += p3 * q1;
123 Z41 += p4 * q1;
124 /* load p and q values */
125 p1=ell[8];
126 q1=ex[8];
127 p2=ell[8+lskip1];
128 p3=ell[8+lskip2];
129 p4=ell[8+lskip3];
130 /* compute outer product and add it to the Z matrix */
131 Z11 += p1 * q1;
132 Z21 += p2 * q1;
133 Z31 += p3 * q1;
134 Z41 += p4 * q1;
135 /* load p and q values */
136 p1=ell[9];
137 q1=ex[9];
138 p2=ell[9+lskip1];
139 p3=ell[9+lskip2];
140 p4=ell[9+lskip3];
141 /* compute outer product and add it to the Z matrix */
142 Z11 += p1 * q1;
143 Z21 += p2 * q1;
144 Z31 += p3 * q1;
145 Z41 += p4 * q1;
146 /* load p and q values */
147 p1=ell[10];
148 q1=ex[10];
149 p2=ell[10+lskip1];
150 p3=ell[10+lskip2];
151 p4=ell[10+lskip3];
152 /* compute outer product and add it to the Z matrix */
153 Z11 += p1 * q1;
154 Z21 += p2 * q1;
155 Z31 += p3 * q1;
156 Z41 += p4 * q1;
157 /* load p and q values */
158 p1=ell[11];
159 q1=ex[11];
160 p2=ell[11+lskip1];
161 p3=ell[11+lskip2];
162 p4=ell[11+lskip3];
163 /* compute outer product and add it to the Z matrix */
164 Z11 += p1 * q1;
165 Z21 += p2 * q1;
166 Z31 += p3 * q1;
167 Z41 += p4 * q1;
168 /* advance pointers */
169 ell += 12;
170 ex += 12;
171 /* end of inner loop */
172 }
173 /* compute left-over iterations */
174 j += 12;
175 for (; j > 0; j--) {
176 /* load p and q values */
177 p1=ell[0];
178 q1=ex[0];
179 p2=ell[lskip1];
180 p3=ell[lskip2];
181 p4=ell[lskip3];
182 /* compute outer product and add it to the Z matrix */
183 Z11 += p1 * q1;
184 Z21 += p2 * q1;
185 Z31 += p3 * q1;
186 Z41 += p4 * q1;
187 /* advance pointers */
188 ell += 1;
189 ex += 1;
190 }
191 /* finish computing the X(i) block */
192 Z11 = ex[0] - Z11;
193 ex[0] = Z11;
194 p1 = ell[lskip1];
195 Z21 = ex[1] - Z21 - p1*Z11;
196 ex[1] = Z21;
197 p1 = ell[lskip2];
198 p2 = ell[1+lskip2];
199 Z31 = ex[2] - Z31 - p1*Z11 - p2*Z21;
200 ex[2] = Z31;
201 p1 = ell[lskip3];
202 p2 = ell[1+lskip3];
203 p3 = ell[2+lskip3];
204 Z41 = ex[3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
205 ex[3] = Z41;
206 /* end of outer loop */
207 }
208 /* compute rows at end that are not a multiple of block size */
209 for (; i < n; i++) {
210 /* compute all 1 x 1 block of X, from rows i..i+1-1 */
211 /* set the Z matrix to 0 */
212 Z11=0;
213 ell = L + i*lskip1;
214 ex = B;
215 /* the inner loop that computes outer products and adds them to Z */
216 for (j=i-12; j >= 0; j -= 12) {
217 /* load p and q values */
218 p1=ell[0];
219 q1=ex[0];
220 /* compute outer product and add it to the Z matrix */
221 Z11 += p1 * q1;
222 /* load p and q values */
223 p1=ell[1];
224 q1=ex[1];
225 /* compute outer product and add it to the Z matrix */
226 Z11 += p1 * q1;
227 /* load p and q values */
228 p1=ell[2];
229 q1=ex[2];
230 /* compute outer product and add it to the Z matrix */
231 Z11 += p1 * q1;
232 /* load p and q values */
233 p1=ell[3];
234 q1=ex[3];
235 /* compute outer product and add it to the Z matrix */
236 Z11 += p1 * q1;
237 /* load p and q values */
238 p1=ell[4];
239 q1=ex[4];
240 /* compute outer product and add it to the Z matrix */
241 Z11 += p1 * q1;
242 /* load p and q values */
243 p1=ell[5];
244 q1=ex[5];
245 /* compute outer product and add it to the Z matrix */
246 Z11 += p1 * q1;
247 /* load p and q values */
248 p1=ell[6];
249 q1=ex[6];
250 /* compute outer product and add it to the Z matrix */
251 Z11 += p1 * q1;
252 /* load p and q values */
253 p1=ell[7];
254 q1=ex[7];
255 /* compute outer product and add it to the Z matrix */
256 Z11 += p1 * q1;
257 /* load p and q values */
258 p1=ell[8];
259 q1=ex[8];
260 /* compute outer product and add it to the Z matrix */
261 Z11 += p1 * q1;
262 /* load p and q values */
263 p1=ell[9];
264 q1=ex[9];
265 /* compute outer product and add it to the Z matrix */
266 Z11 += p1 * q1;
267 /* load p and q values */
268 p1=ell[10];
269 q1=ex[10];
270 /* compute outer product and add it to the Z matrix */
271 Z11 += p1 * q1;
272 /* load p and q values */
273 p1=ell[11];
274 q1=ex[11];
275 /* compute outer product and add it to the Z matrix */
276 Z11 += p1 * q1;
277 /* advance pointers */
278 ell += 12;
279 ex += 12;
280 /* end of inner loop */
281 }
282 /* compute left-over iterations */
283 j += 12;
284 for (; j > 0; j--) {
285 /* load p and q values */
286 p1=ell[0];
287 q1=ex[0];
288 /* compute outer product and add it to the Z matrix */
289 Z11 += p1 * q1;
290 /* advance pointers */
291 ell += 1;
292 ex += 1;
293 }
294 /* finish computing the X(i) block */
295 Z11 = ex[0] - Z11;
296 ex[0] = Z11;
297 }
298}
diff --git a/libraries/ode-0.9/ode/src/fastltsolve.c b/libraries/ode-0.9/ode/src/fastltsolve.c
deleted file mode 100644
index eb950f6..0000000
--- a/libraries/ode-0.9/ode/src/fastltsolve.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/* generated code, do not edit. */
2
3#include "ode/matrix.h"
4
5/* solve L^T * x=b, with b containing 1 right hand side.
6 * L is an n*n lower triangular matrix with ones on the diagonal.
7 * L is stored by rows and its leading dimension is lskip.
8 * b is an n*1 matrix that contains the right hand side.
9 * b is overwritten with x.
10 * this processes blocks of 4.
11 */
12
13void dSolveL1T (const dReal *L, dReal *B, int n, int lskip1)
14{
15 /* declare variables - Z matrix, p and q vectors, etc */
16 dReal Z11,m11,Z21,m21,Z31,m31,Z41,m41,p1,q1,p2,p3,p4,*ex;
17 const dReal *ell;
18 int lskip2,lskip3,i,j;
19 /* special handling for L and B because we're solving L1 *transpose* */
20 L = L + (n-1)*(lskip1+1);
21 B = B + n-1;
22 lskip1 = -lskip1;
23 /* compute lskip values */
24 lskip2 = 2*lskip1;
25 lskip3 = 3*lskip1;
26 /* compute all 4 x 1 blocks of X */
27 for (i=0; i <= n-4; i+=4) {
28 /* compute all 4 x 1 block of X, from rows i..i+4-1 */
29 /* set the Z matrix to 0 */
30 Z11=0;
31 Z21=0;
32 Z31=0;
33 Z41=0;
34 ell = L - i;
35 ex = B;
36 /* the inner loop that computes outer products and adds them to Z */
37 for (j=i-4; j >= 0; j -= 4) {
38 /* load p and q values */
39 p1=ell[0];
40 q1=ex[0];
41 p2=ell[-1];
42 p3=ell[-2];
43 p4=ell[-3];
44 /* compute outer product and add it to the Z matrix */
45 m11 = p1 * q1;
46 m21 = p2 * q1;
47 m31 = p3 * q1;
48 m41 = p4 * q1;
49 ell += lskip1;
50 Z11 += m11;
51 Z21 += m21;
52 Z31 += m31;
53 Z41 += m41;
54 /* load p and q values */
55 p1=ell[0];
56 q1=ex[-1];
57 p2=ell[-1];
58 p3=ell[-2];
59 p4=ell[-3];
60 /* compute outer product and add it to the Z matrix */
61 m11 = p1 * q1;
62 m21 = p2 * q1;
63 m31 = p3 * q1;
64 m41 = p4 * q1;
65 ell += lskip1;
66 Z11 += m11;
67 Z21 += m21;
68 Z31 += m31;
69 Z41 += m41;
70 /* load p and q values */
71 p1=ell[0];
72 q1=ex[-2];
73 p2=ell[-1];
74 p3=ell[-2];
75 p4=ell[-3];
76 /* compute outer product and add it to the Z matrix */
77 m11 = p1 * q1;
78 m21 = p2 * q1;
79 m31 = p3 * q1;
80 m41 = p4 * q1;
81 ell += lskip1;
82 Z11 += m11;
83 Z21 += m21;
84 Z31 += m31;
85 Z41 += m41;
86 /* load p and q values */
87 p1=ell[0];
88 q1=ex[-3];
89 p2=ell[-1];
90 p3=ell[-2];
91 p4=ell[-3];
92 /* compute outer product and add it to the Z matrix */
93 m11 = p1 * q1;
94 m21 = p2 * q1;
95 m31 = p3 * q1;
96 m41 = p4 * q1;
97 ell += lskip1;
98 ex -= 4;
99 Z11 += m11;
100 Z21 += m21;
101 Z31 += m31;
102 Z41 += m41;
103 /* end of inner loop */
104 }
105 /* compute left-over iterations */
106 j += 4;
107 for (; j > 0; j--) {
108 /* load p and q values */
109 p1=ell[0];
110 q1=ex[0];
111 p2=ell[-1];
112 p3=ell[-2];
113 p4=ell[-3];
114 /* compute outer product and add it to the Z matrix */
115 m11 = p1 * q1;
116 m21 = p2 * q1;
117 m31 = p3 * q1;
118 m41 = p4 * q1;
119 ell += lskip1;
120 ex -= 1;
121 Z11 += m11;
122 Z21 += m21;
123 Z31 += m31;
124 Z41 += m41;
125 }
126 /* finish computing the X(i) block */
127 Z11 = ex[0] - Z11;
128 ex[0] = Z11;
129 p1 = ell[-1];
130 Z21 = ex[-1] - Z21 - p1*Z11;
131 ex[-1] = Z21;
132 p1 = ell[-2];
133 p2 = ell[-2+lskip1];
134 Z31 = ex[-2] - Z31 - p1*Z11 - p2*Z21;
135 ex[-2] = Z31;
136 p1 = ell[-3];
137 p2 = ell[-3+lskip1];
138 p3 = ell[-3+lskip2];
139 Z41 = ex[-3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
140 ex[-3] = Z41;
141 /* end of outer loop */
142 }
143 /* compute rows at end that are not a multiple of block size */
144 for (; i < n; i++) {
145 /* compute all 1 x 1 block of X, from rows i..i+1-1 */
146 /* set the Z matrix to 0 */
147 Z11=0;
148 ell = L - i;
149 ex = B;
150 /* the inner loop that computes outer products and adds them to Z */
151 for (j=i-4; j >= 0; j -= 4) {
152 /* load p and q values */
153 p1=ell[0];
154 q1=ex[0];
155 /* compute outer product and add it to the Z matrix */
156 m11 = p1 * q1;
157 ell += lskip1;
158 Z11 += m11;
159 /* load p and q values */
160 p1=ell[0];
161 q1=ex[-1];
162 /* compute outer product and add it to the Z matrix */
163 m11 = p1 * q1;
164 ell += lskip1;
165 Z11 += m11;
166 /* load p and q values */
167 p1=ell[0];
168 q1=ex[-2];
169 /* compute outer product and add it to the Z matrix */
170 m11 = p1 * q1;
171 ell += lskip1;
172 Z11 += m11;
173 /* load p and q values */
174 p1=ell[0];
175 q1=ex[-3];
176 /* compute outer product and add it to the Z matrix */
177 m11 = p1 * q1;
178 ell += lskip1;
179 ex -= 4;
180 Z11 += m11;
181 /* end of inner loop */
182 }
183 /* compute left-over iterations */
184 j += 4;
185 for (; j > 0; j--) {
186 /* load p and q values */
187 p1=ell[0];
188 q1=ex[0];
189 /* compute outer product and add it to the Z matrix */
190 m11 = p1 * q1;
191 ell += lskip1;
192 ex -= 1;
193 Z11 += m11;
194 }
195 /* finish computing the X(i) block */
196 Z11 = ex[0] - Z11;
197 ex[0] = Z11;
198 }
199}
diff --git a/libraries/ode-0.9/ode/src/heightfield.cpp b/libraries/ode-0.9/ode/src/heightfield.cpp
deleted file mode 100644
index 36755fc..0000000
--- a/libraries/ode-0.9/ode/src/heightfield.cpp
+++ /dev/null
@@ -1,1812 +0,0 @@
1// dHeightfield Collider
2// Paul Cheyrou-Lagreze aka Tuan Kuranes 2006 Speed enhancements http://www.pop-3d.com
3// Martijn Buijs 2006 http://home.planet.nl/~buijs512/
4// Based on Terrain & Cone contrib by:
5// Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
6// Some code inspired by Magic Software
7
8
9#include <ode/common.h>
10#include <ode/collision.h>
11#include <ode/matrix.h>
12#include <ode/rotation.h>
13#include <ode/odemath.h>
14#include "collision_kernel.h"
15#include "collision_std.h"
16#include "collision_util.h"
17#include "heightfield.h"
18
19
20
21#if dTRIMESH_ENABLED
22#include "collision_trimesh_internal.h"
23#endif // dTRIMESH_ENABLED
24
25#define TERRAINTOL REAL(0.0)
26
27#define dMIN(A,B) ((A)>(B) ? B : A)
28#define dMAX(A,B) ((A)>(B) ? A : B)
29
30
31// Three-way MIN and MAX
32#define dMIN3(A,B,C) ( (A)<(B) ? dMIN((A),(C)) : dMIN((B),(C)) )
33#define dMAX3(A,B,C) ( (A)>(B) ? dMAX((A),(C)) : dMAX((B),(C)) )
34
35#define dOPESIGN(a, op1, op2,b) \
36 (a)[0] op1 op2 ((b)[0]); \
37 (a)[1] op1 op2 ((b)[1]); \
38 (a)[2] op1 op2 ((b)[2]);
39
40#define dGeomRaySetNoNormalize(myRay, MyPoint, MyVector) { \
41 \
42 dVector3Copy (MyPoint, myRay.final_posr->pos); \
43 myRay.final_posr->R[2] = MyVector[0]; \
44 myRay.final_posr->R[6] = MyVector[1]; \
45 myRay.final_posr->R[10] = MyVector[2]; \
46 dGeomMoved (&myRay); \
47 }
48
49#define dGeomPlaneSetNoNormalize(MyPlane, MyPlaneDef) { \
50 \
51 MyPlane->p[0] = MyPlaneDef[0]; \
52 MyPlane->p[1] = MyPlaneDef[1]; \
53 MyPlane->p[2] = MyPlaneDef[2]; \
54 MyPlane->p[3] = MyPlaneDef[3]; \
55 dGeomMoved (MyPlane); \
56 }
57//////// Local Build Option ////////////////////////////////////////////////////
58
59// Uncomment this #define to use the (0,0) corner of the geom as the origin,
60// rather than the center. This was the way the original heightfield worked,
61// but as it does not match the way all other geometries work, so for constancy it
62// was changed to work like this.
63
64// #define DHEIGHTFIELD_CORNER_ORIGIN
65
66
67// Uncomment this #define to add heightfield triangles edge colliding
68// Code is not guaranteed and I didn't find the need to add that as
69// colliding planes triangles and edge triangles seems enough.
70// #define _HEIGHTFIELDEDGECOLLIDING
71
72
73//////// dxHeightfieldData /////////////////////////////////////////////////////////////
74
75// dxHeightfieldData constructor
76dxHeightfieldData::dxHeightfieldData()
77{
78 //
79}
80
81
82// build Heightfield data
83void dxHeightfieldData::SetData( int nWidthSamples, int nDepthSamples,
84 dReal fWidth, dReal fDepth,
85 dReal fScale, dReal fOffset, dReal fThickness,
86 int bWrapMode )
87{
88 dIASSERT( fWidth > REAL( 0.0 ) );
89 dIASSERT( fDepth > REAL( 0.0 ) );
90 dIASSERT( nWidthSamples > 0 );
91 dIASSERT( nDepthSamples > 0 );
92
93 // x,z bounds
94 m_fWidth = fWidth;
95 m_fDepth = fDepth;
96
97 // cache half x,z bounds
98 m_fHalfWidth = fWidth / REAL( 2.0 );
99 m_fHalfDepth = fDepth / REAL( 2.0 );
100
101 // scale and offset
102 m_fScale = fScale;
103 m_fOffset = fOffset;
104
105 // infinite min height bounds
106 m_fThickness = fThickness;
107
108 // number of vertices per side
109 m_nWidthSamples = nWidthSamples;
110 m_nDepthSamples = nDepthSamples;
111
112 m_fSampleWidth = m_fWidth / ( m_nWidthSamples - 1 );
113 m_fSampleDepth = m_fDepth / ( m_nDepthSamples - 1 );
114
115 m_fInvSampleWidth = 1 / m_fSampleWidth;
116 m_fInvSampleDepth = 1 / m_fSampleDepth;
117
118 // finite or repeated terrain?
119 m_bWrapMode = bWrapMode;
120}
121
122
123// recomputes heights bounds
124void dxHeightfieldData::ComputeHeightBounds()
125{
126 static int i;
127 static dReal h;
128 static unsigned char *data_byte;
129 static short *data_short;
130 static float *data_float;
131 static double *data_double;
132
133 switch ( m_nGetHeightMode )
134 {
135
136 // callback
137 case 0:
138 // change nothing, keep using default or user specified bounds
139 return;
140
141 // byte
142 case 1:
143 data_byte = (unsigned char*)m_pHeightData;
144 m_fMinHeight = dInfinity;
145 m_fMaxHeight = -dInfinity;
146
147 for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
148 {
149 h = data_byte[i];
150 if (h < m_fMinHeight) m_fMinHeight = h;
151 if (h > m_fMaxHeight) m_fMaxHeight = h;
152 }
153
154 break;
155
156 // short
157 case 2:
158 data_short = (short*)m_pHeightData;
159 m_fMinHeight = dInfinity;
160 m_fMaxHeight = -dInfinity;
161
162 for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
163 {
164 h = data_short[i];
165 if (h < m_fMinHeight) m_fMinHeight = h;
166 if (h > m_fMaxHeight) m_fMaxHeight = h;
167 }
168
169 break;
170
171 // float
172 case 3:
173 data_float = (float*)m_pHeightData;
174 m_fMinHeight = dInfinity;
175 m_fMaxHeight = -dInfinity;
176
177 for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
178 {
179 h = data_float[i];
180 if (h < m_fMinHeight) m_fMinHeight = h;
181 if (h > m_fMaxHeight) m_fMaxHeight = h;
182 }
183
184 break;
185
186 // double
187 case 4:
188 data_double = (double*)m_pHeightData;
189 m_fMinHeight = dInfinity;
190 m_fMaxHeight = -dInfinity;
191
192 for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
193 {
194 h = static_cast< dReal >( data_double[i] );
195 if (h < m_fMinHeight) m_fMinHeight = h;
196 if (h > m_fMaxHeight) m_fMaxHeight = h;
197 }
198
199 break;
200
201 }
202
203 // scale and offset
204 m_fMinHeight *= m_fScale;
205 m_fMaxHeight *= m_fScale;
206 m_fMinHeight += m_fOffset;
207 m_fMaxHeight += m_fOffset;
208
209 // add thickness
210 m_fMinHeight -= m_fThickness;
211}
212
213
214// returns whether point is over terrain Cell triangle?
215bool dxHeightfieldData::IsOnHeightfield ( const dReal * const CellOrigin, const dReal * const pos, const bool isABC) const
216{
217 {
218 const dReal MaxX = CellOrigin[0] + m_fSampleWidth;
219 const dReal TolX = m_fSampleWidth * TERRAINTOL;
220 if ((pos[0]<CellOrigin[0]-TolX) || (pos[0]>MaxX+TolX))
221 return false;
222 }
223
224 {
225 const dReal MaxZ = CellOrigin[2] + m_fSampleDepth;
226 const dReal TolZ = m_fSampleDepth * TERRAINTOL;
227 if ((pos[2]<CellOrigin[2]-TolZ) || (pos[2]>MaxZ+TolZ))
228 return false;
229 }
230
231 // add X percentage position on cell and Z percentage position on cell
232 const dReal pctTotal = (pos[0] - CellOrigin[0]) * m_fInvSampleWidth
233 + (pos[2] - CellOrigin[2]) * m_fInvSampleDepth;
234
235 if (isABC)
236 {
237 if (pctTotal >= REAL(1.0) + TERRAINTOL)
238 return false;
239 else
240 return true;
241 }
242 else if (pctTotal <= REAL(1.0) - TERRAINTOL)
243 {
244 return false;
245 }
246 return true;
247}
248// returns whether point is over terrain Cell triangle?
249bool dxHeightfieldData::IsOnHeightfield2 ( const dReal * const CellOrigin, const dReal * const pos, const bool isABC) const
250{
251 dReal MaxX, MinX;
252 dReal MaxZ, MinZ;
253 if (isABC)
254 {
255 // point A
256 MinX = CellOrigin[0];
257 MaxX = CellOrigin[0] + m_fSampleWidth;
258
259 MinZ = CellOrigin[2];
260 MaxZ = CellOrigin[2] + m_fSampleDepth;
261 }
262 else
263 {
264 // point D
265 MinX = CellOrigin[0] - m_fSampleWidth;
266 MaxX = CellOrigin[0];
267
268 MinZ = CellOrigin[2] - m_fSampleDepth;
269 MaxZ = CellOrigin[2];
270 }
271
272 // check if inside CELL
273 {
274 const dReal TolX = m_fSampleWidth * TERRAINTOL;
275 if ((pos[0]<MinX-TolX) || (pos[0]>MaxX+TolX))
276 return false;
277 }
278
279 {
280 const dReal TolZ = m_fSampleDepth * TERRAINTOL;
281 if ((pos[2]<MinZ-TolZ) || (pos[2]>MaxZ+TolZ))
282 return false;
283 }
284
285 // Sum up X percentage position on cell and Z percentage position on cell
286 const dReal pctTotal = (pos[0] - MinX) * m_fInvSampleWidth
287 + (pos[2] - MinZ) * m_fInvSampleDepth;
288
289 // check if inside respective Triangle of Cell
290 if (isABC)
291 {
292 if (pctTotal >= REAL(1.0) + TERRAINTOL)
293 return false;
294 else
295 return true;
296 }
297 else if (pctTotal <= REAL(1.0) - TERRAINTOL)
298 {
299 return false;
300 }
301 return true;
302}
303
304
305// returns height at given sample coordinates
306dReal dxHeightfieldData::GetHeight( int x, int z )
307{
308 static dReal h;
309 static unsigned char *data_byte;
310 static short *data_short;
311 static float *data_float;
312 static double *data_double;
313
314 if ( m_bWrapMode == 0 )
315 {
316 // Finite
317 if ( x < 0 ) x = 0;
318 if ( z < 0 ) z = 0;
319 if ( x > m_nWidthSamples - 1 ) x = m_nWidthSamples - 1;
320 if ( z > m_nDepthSamples - 1 ) z = m_nDepthSamples - 1;
321 }
322 else
323 {
324 // Infinite
325 x %= m_nWidthSamples - 1;
326 z %= m_nDepthSamples - 1;
327 if ( x < 0 ) x += m_nWidthSamples - 1;
328 if ( z < 0 ) z += m_nDepthSamples - 1;
329 }
330
331 switch ( m_nGetHeightMode )
332 {
333
334 // callback (dReal)
335 case 0:
336 h = (*m_pGetHeightCallback)(m_pUserData, x, z);
337 break;
338
339 // byte
340 case 1:
341 data_byte = (unsigned char*)m_pHeightData;
342 h = data_byte[x+(z * m_nWidthSamples)];
343 break;
344
345 // short
346 case 2:
347 data_short = (short*)m_pHeightData;
348 h = data_short[x+(z * m_nWidthSamples)];
349 break;
350
351 // float
352 case 3:
353 data_float = (float*)m_pHeightData;
354 h = data_float[x+(z * m_nWidthSamples)];
355 break;
356
357 // double
358 case 4:
359 data_double = (double*)m_pHeightData;
360 h = static_cast< dReal >( data_double[x+(z * m_nWidthSamples)] );
361 break;
362 }
363
364 return (h * m_fScale) + m_fOffset;
365}
366
367
368// returns height at given coordinates
369dReal dxHeightfieldData::GetHeight( dReal x, dReal z )
370{
371 dReal dnX = dFloor( x * m_fInvSampleWidth );
372 dReal dnZ = dFloor( z * m_fInvSampleDepth );
373
374 dReal dx = ( x - ( dnX * m_fSampleWidth ) ) * m_fInvSampleWidth;
375 dReal dz = ( z - ( dnZ * m_fSampleDepth ) ) * m_fInvSampleDepth;
376
377 int nX = int( dnX );
378 int nZ = int( dnZ );
379
380 //dIASSERT( ( dx + dEpsilon >= 0.0f ) && ( dx - dEpsilon <= 1.0f ) );
381 //dIASSERT( ( dz + dEpsilon >= 0.0f ) && ( dz - dEpsilon <= 1.0f ) );
382
383 dReal y, y0;
384
385 if ( dx + dz < REAL( 1.0 ) )
386 {
387 y0 = GetHeight( nX, nZ );
388
389 y = y0 + ( GetHeight( nX + 1, nZ ) - y0 ) * dx
390 + ( GetHeight( nX, nZ + 1 ) - y0 ) * dz;
391 }
392 else
393 {
394 y0 = GetHeight( nX + 1, nZ + 1 );
395
396 y = y0 + ( GetHeight( nX + 1, nZ ) - y0 ) * ( REAL(1.0) - dz ) +
397 ( GetHeight( nX, nZ + 1 ) - y0 ) * ( REAL(1.0) - dx );
398 }
399
400 return y;
401}
402
403
404// dxHeightfieldData destructor
405dxHeightfieldData::~dxHeightfieldData()
406{
407 static unsigned char *data_byte;
408 static short *data_short;
409 static float *data_float;
410 static double *data_double;
411
412 dIASSERT( m_pHeightData );
413
414 if ( m_bCopyHeightData )
415 {
416 switch ( m_nGetHeightMode )
417 {
418
419 // callback
420 case 0:
421 // do nothing
422 break;
423
424 // byte
425 case 1:
426 data_byte = (unsigned char*)m_pHeightData;
427 delete [] data_byte;
428 break;
429
430 // short
431 case 2:
432 data_short = (short*)m_pHeightData;
433 delete [] data_short;
434 break;
435
436 // float
437 case 3:
438 data_float = (float*)m_pHeightData;
439 delete [] data_float;
440 break;
441
442 // double
443 case 4:
444 data_double = (double*)m_pHeightData;
445 delete [] data_double;
446 break;
447
448 }
449 }
450}
451
452
453//////// dxHeightfield /////////////////////////////////////////////////////////////////
454
455
456// dxHeightfield constructor
457dxHeightfield::dxHeightfield( dSpaceID space,
458 dHeightfieldDataID data,
459 int bPlaceable ) :
460 dxGeom( space, bPlaceable ),
461 tempPlaneBuffer(0),
462 tempPlaneInstances(0),
463 tempPlaneBufferSize(0),
464 tempTriangleBuffer(0),
465 tempTriangleBufferSize(0),
466 tempHeightBuffer(0),
467 tempHeightInstances(0),
468 tempHeightBufferSizeX(0),
469 tempHeightBufferSizeZ(0)
470{
471 type = dHeightfieldClass;
472 this->m_p_data = data;
473}
474
475
476// compute axis aligned bounding box
477void dxHeightfield::computeAABB()
478{
479 const dxHeightfieldData *d = m_p_data;
480
481 if ( d->m_bWrapMode == 0 )
482 {
483 // Finite
484 if ( gflags & GEOM_PLACEABLE )
485 {
486 dReal dx[6], dy[6], dz[6];
487
488 // Y-axis
489 dy[0] = ( final_posr->R[ 1] * d->m_fMinHeight );
490 dy[1] = ( final_posr->R[ 5] * d->m_fMinHeight );
491 dy[2] = ( final_posr->R[ 9] * d->m_fMinHeight );
492 dy[3] = ( final_posr->R[ 1] * d->m_fMaxHeight );
493 dy[4] = ( final_posr->R[ 5] * d->m_fMaxHeight );
494 dy[5] = ( final_posr->R[ 9] * d->m_fMaxHeight );
495
496#ifdef DHEIGHTFIELD_CORNER_ORIGIN
497
498 // X-axis
499 dx[0] = 0; dx[3] = ( final_posr->R[ 0] * d->m_fWidth );
500 dx[1] = 0; dx[4] = ( final_posr->R[ 4] * d->m_fWidth );
501 dx[2] = 0; dx[5] = ( final_posr->R[ 8] * d->m_fWidth );
502
503 // Z-axis
504 dz[0] = 0; dz[3] = ( final_posr->R[ 2] * d->m_fDepth );
505 dz[1] = 0; dz[4] = ( final_posr->R[ 6] * d->m_fDepth );
506 dz[2] = 0; dz[5] = ( final_posr->R[10] * d->m_fDepth );
507
508#else // DHEIGHTFIELD_CORNER_ORIGIN
509
510 // X-axis
511 dx[0] = ( final_posr->R[ 0] * -d->m_fHalfWidth );
512 dx[1] = ( final_posr->R[ 4] * -d->m_fHalfWidth );
513 dx[2] = ( final_posr->R[ 8] * -d->m_fHalfWidth );
514 dx[3] = ( final_posr->R[ 0] * d->m_fHalfWidth );
515 dx[4] = ( final_posr->R[ 4] * d->m_fHalfWidth );
516 dx[5] = ( final_posr->R[ 8] * d->m_fHalfWidth );
517
518 // Z-axis
519 dz[0] = ( final_posr->R[ 2] * -d->m_fHalfDepth );
520 dz[1] = ( final_posr->R[ 6] * -d->m_fHalfDepth );
521 dz[2] = ( final_posr->R[10] * -d->m_fHalfDepth );
522 dz[3] = ( final_posr->R[ 2] * d->m_fHalfDepth );
523 dz[4] = ( final_posr->R[ 6] * d->m_fHalfDepth );
524 dz[5] = ( final_posr->R[10] * d->m_fHalfDepth );
525
526#endif // DHEIGHTFIELD_CORNER_ORIGIN
527
528 // X extents
529 aabb[0] = final_posr->pos[0] +
530 dMIN3( dMIN( dx[0], dx[3] ), dMIN( dy[0], dy[3] ), dMIN( dz[0], dz[3] ) );
531 aabb[1] = final_posr->pos[0] +
532 dMAX3( dMAX( dx[0], dx[3] ), dMAX( dy[0], dy[3] ), dMAX( dz[0], dz[3] ) );
533
534 // Y extents
535 aabb[2] = final_posr->pos[1] +
536 dMIN3( dMIN( dx[1], dx[4] ), dMIN( dy[1], dy[4] ), dMIN( dz[1], dz[4] ) );
537 aabb[3] = final_posr->pos[1] +
538 dMAX3( dMAX( dx[1], dx[4] ), dMAX( dy[1], dy[4] ), dMAX( dz[1], dz[4] ) );
539
540 // Z extents
541 aabb[4] = final_posr->pos[2] +
542 dMIN3( dMIN( dx[2], dx[5] ), dMIN( dy[2], dy[5] ), dMIN( dz[2], dz[5] ) );
543 aabb[5] = final_posr->pos[2] +
544 dMAX3( dMAX( dx[2], dx[5] ), dMAX( dy[2], dy[5] ), dMAX( dz[2], dz[5] ) );
545 }
546 else
547 {
548
549#ifdef DHEIGHTFIELD_CORNER_ORIGIN
550
551 aabb[0] = 0; aabb[1] = d->m_fWidth;
552 aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight;
553 aabb[4] = 0; aabb[5] = d->m_fDepth;
554
555#else // DHEIGHTFIELD_CORNER_ORIGIN
556
557 aabb[0] = -d->m_fHalfWidth; aabb[1] = +d->m_fHalfWidth;
558 aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight;
559 aabb[4] = -d->m_fHalfDepth; aabb[5] = +d->m_fHalfDepth;
560
561#endif // DHEIGHTFIELD_CORNER_ORIGIN
562
563 }
564 }
565 else
566 {
567 // Infinite
568 if ( gflags & GEOM_PLACEABLE )
569 {
570 aabb[0] = -dInfinity; aabb[1] = +dInfinity;
571 aabb[2] = -dInfinity; aabb[3] = +dInfinity;
572 aabb[4] = -dInfinity; aabb[5] = +dInfinity;
573 }
574 else
575 {
576 aabb[0] = -dInfinity; aabb[1] = +dInfinity;
577 aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight;
578 aabb[4] = -dInfinity; aabb[5] = +dInfinity;
579 }
580 }
581
582}
583
584
585// dxHeightfield destructor
586dxHeightfield::~dxHeightfield()
587{
588 resetTriangleBuffer();
589 resetPlaneBuffer();
590 resetHeightBuffer();
591}
592
593void dxHeightfield::allocateTriangleBuffer(size_t numTri)
594{
595 size_t alignedNumTri = AlignBufferSize(numTri, TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT);
596 tempTriangleBufferSize = alignedNumTri;
597 tempTriangleBuffer = new HeightFieldTriangle[alignedNumTri];
598}
599
600void dxHeightfield::resetTriangleBuffer()
601{
602 delete[] tempTriangleBuffer;
603}
604
605void dxHeightfield::allocatePlaneBuffer(size_t numTri)
606{
607 size_t alignedNumTri = AlignBufferSize(numTri, TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT);
608 tempPlaneBufferSize = alignedNumTri;
609 tempPlaneBuffer = new HeightFieldPlane *[alignedNumTri];
610 tempPlaneInstances = new HeightFieldPlane[alignedNumTri];
611
612 HeightFieldPlane *ptrPlaneMatrix = tempPlaneInstances;
613 for (size_t indexTri = 0; indexTri != alignedNumTri; indexTri++)
614 {
615 tempPlaneBuffer[indexTri] = ptrPlaneMatrix;
616 ptrPlaneMatrix += 1;
617 }
618}
619
620void dxHeightfield::resetPlaneBuffer()
621{
622 delete[] tempPlaneInstances;
623 delete[] tempPlaneBuffer;
624}
625
626void dxHeightfield::allocateHeightBuffer(size_t numX, size_t numZ)
627{
628 size_t alignedNumX = AlignBufferSize(numX, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X);
629 size_t alignedNumZ = AlignBufferSize(numZ, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z);
630 tempHeightBufferSizeX = alignedNumX;
631 tempHeightBufferSizeZ = alignedNumZ;
632 tempHeightBuffer = new HeightFieldVertex *[alignedNumX];
633 size_t numCells = alignedNumX * alignedNumZ;
634 tempHeightInstances = new HeightFieldVertex [numCells];
635
636 HeightFieldVertex *ptrHeightMatrix = tempHeightInstances;
637 for (size_t indexX = 0; indexX != alignedNumX; indexX++)
638 {
639 tempHeightBuffer[indexX] = ptrHeightMatrix;
640 ptrHeightMatrix += alignedNumZ;
641 }
642}
643
644void dxHeightfield::resetHeightBuffer()
645{
646 delete[] tempHeightInstances;
647 delete[] tempHeightBuffer;
648}
649//////// Heightfield data interface ////////////////////////////////////////////////////
650
651
652dHeightfieldDataID dGeomHeightfieldDataCreate()
653{
654 return new dxHeightfieldData();
655}
656
657
658void dGeomHeightfieldDataBuildCallback( dHeightfieldDataID d,
659 void* pUserData, dHeightfieldGetHeight* pCallback,
660 dReal width, dReal depth, int widthSamples, int depthSamples,
661 dReal scale, dReal offset, dReal thickness, int bWrap )
662{
663 dUASSERT( d, "argument not Heightfield data" );
664 dIASSERT( pCallback );
665 dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell.
666 dIASSERT( depthSamples >= 2 );
667
668 // callback
669 d->m_nGetHeightMode = 0;
670 d->m_pUserData = pUserData;
671 d->m_pGetHeightCallback = pCallback;
672
673 // set info
674 d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
675
676 // default bounds
677 d->m_fMinHeight = -dInfinity;
678 d->m_fMaxHeight = dInfinity;
679}
680
681
682void dGeomHeightfieldDataBuildByte( dHeightfieldDataID d,
683 const unsigned char *pHeightData, int bCopyHeightData,
684 dReal width, dReal depth, int widthSamples, int depthSamples,
685 dReal scale, dReal offset, dReal thickness, int bWrap )
686{
687 dUASSERT( d, "Argument not Heightfield data" );
688 dIASSERT( pHeightData );
689 dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell.
690 dIASSERT( depthSamples >= 2 );
691
692 // set info
693 d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
694 d->m_nGetHeightMode = 1;
695 d->m_bCopyHeightData = bCopyHeightData;
696
697 if ( d->m_bCopyHeightData == 0 )
698 {
699 // Data is referenced only.
700 d->m_pHeightData = pHeightData;
701 }
702 else
703 {
704 // We own the height data, allocate storage
705 d->m_pHeightData = new unsigned char[ d->m_nWidthSamples * d->m_nDepthSamples ];
706 dIASSERT( d->m_pHeightData );
707
708 // Copy data.
709 memcpy( (void*)d->m_pHeightData, pHeightData,
710 sizeof( unsigned char ) * d->m_nWidthSamples * d->m_nDepthSamples );
711 }
712
713 // Find height bounds
714 d->ComputeHeightBounds();
715}
716
717
718void dGeomHeightfieldDataBuildShort( dHeightfieldDataID d,
719 const short* pHeightData, int bCopyHeightData,
720 dReal width, dReal depth, int widthSamples, int depthSamples,
721 dReal scale, dReal offset, dReal thickness, int bWrap )
722{
723 dUASSERT( d, "Argument not Heightfield data" );
724 dIASSERT( pHeightData );
725 dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell.
726 dIASSERT( depthSamples >= 2 );
727
728 // set info
729 d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
730 d->m_nGetHeightMode = 2;
731 d->m_bCopyHeightData = bCopyHeightData;
732
733 if ( d->m_bCopyHeightData == 0 )
734 {
735 // Data is referenced only.
736 d->m_pHeightData = pHeightData;
737 }
738 else
739 {
740 // We own the height data, allocate storage
741 d->m_pHeightData = new short[ d->m_nWidthSamples * d->m_nDepthSamples ];
742 dIASSERT( d->m_pHeightData );
743
744 // Copy data.
745 memcpy( (void*)d->m_pHeightData, pHeightData,
746 sizeof( short ) * d->m_nWidthSamples * d->m_nDepthSamples );
747 }
748
749 // Find height bounds
750 d->ComputeHeightBounds();
751}
752
753
754void dGeomHeightfieldDataBuildSingle( dHeightfieldDataID d,
755 const float *pHeightData, int bCopyHeightData,
756 dReal width, dReal depth, int widthSamples, int depthSamples,
757 dReal scale, dReal offset, dReal thickness, int bWrap )
758{
759 dUASSERT( d, "Argument not Heightfield data" );
760 dIASSERT( pHeightData );
761 dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell.
762 dIASSERT( depthSamples >= 2 );
763
764 // set info
765 d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
766 d->m_nGetHeightMode = 3;
767 d->m_bCopyHeightData = bCopyHeightData;
768
769 if ( d->m_bCopyHeightData == 0 )
770 {
771 // Data is referenced only.
772 d->m_pHeightData = pHeightData;
773 }
774 else
775 {
776 // We own the height data, allocate storage
777 d->m_pHeightData = new float[ d->m_nWidthSamples * d->m_nDepthSamples ];
778 dIASSERT( d->m_pHeightData );
779
780 // Copy data.
781 memcpy( (void*)d->m_pHeightData, pHeightData,
782 sizeof( float ) * d->m_nWidthSamples * d->m_nDepthSamples );
783 }
784
785 // Find height bounds
786 d->ComputeHeightBounds();
787}
788
789void dGeomHeightfieldDataBuildDouble( dHeightfieldDataID d,
790 const double *pHeightData, int bCopyHeightData,
791 dReal width, dReal depth, int widthSamples, int depthSamples,
792 dReal scale, dReal offset, dReal thickness, int bWrap )
793{
794 dUASSERT( d, "Argument not Heightfield data" );
795 dIASSERT( pHeightData );
796 dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell.
797 dIASSERT( depthSamples >= 2 );
798
799 // set info
800 d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
801 d->m_nGetHeightMode = 4;
802 d->m_bCopyHeightData = bCopyHeightData;
803
804 if ( d->m_bCopyHeightData == 0 )
805 {
806 // Data is referenced only.
807 d->m_pHeightData = pHeightData;
808 }
809 else
810 {
811 // We own the height data, allocate storage
812 d->m_pHeightData = new double[ d->m_nWidthSamples * d->m_nDepthSamples ];
813 dIASSERT( d->m_pHeightData );
814
815 // Copy data.
816 memcpy( (void*)d->m_pHeightData, pHeightData,
817 sizeof( double ) * d->m_nWidthSamples * d->m_nDepthSamples );
818 }
819
820 // Find height bounds
821 d->ComputeHeightBounds();
822}
823
824
825
826
827void dGeomHeightfieldDataSetBounds( dHeightfieldDataID d, dReal minHeight, dReal maxHeight )
828{
829 dUASSERT(d, "Argument not Heightfield data");
830 d->m_fMinHeight = ( minHeight * d->m_fScale ) + d->m_fOffset - d->m_fThickness;
831 d->m_fMaxHeight = ( maxHeight * d->m_fScale ) + d->m_fOffset;
832}
833
834
835void dGeomHeightfieldDataDestroy( dHeightfieldDataID d )
836{
837 dUASSERT(d, "argument not Heightfield data");
838 delete d;
839}
840
841
842//////// Heightfield geom interface ////////////////////////////////////////////////////
843
844
845dGeomID dCreateHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable )
846{
847 return new dxHeightfield( space, data, bPlaceable );
848}
849
850
851void dGeomHeightfieldSetHeightfieldData( dGeomID g, dHeightfieldDataID d )
852{
853 dxHeightfield* geom = (dxHeightfield*) g;
854 geom->data = d;
855}
856
857
858dHeightfieldDataID dGeomHeightfieldGetHeightfieldData( dGeomID g )
859{
860 dxHeightfield* geom = (dxHeightfield*) g;
861 return geom->m_p_data;
862}
863
864//////// dxHeightfield /////////////////////////////////////////////////////////////////
865
866
867// Typedef for generic 'get point depth' function
868typedef dReal dGetDepthFn( dGeomID g, dReal x, dReal y, dReal z );
869
870
871#define DMESS(A) \
872 dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).", \
873 x,z,A, \
874 pContact->depth, \
875 dGeomSphereGetRadius(o2), \
876 pContact->pos[0], \
877 pContact->pos[1], \
878 pContact->pos[2], \
879 pContact->normal[0], \
880 pContact->normal[1], \
881 pContact->normal[2]);
882
883static inline bool DescendingTriangleSort(const HeightFieldTriangle * const A, const HeightFieldTriangle * const B)
884{
885 return ((A->maxAAAB - B->maxAAAB) > dEpsilon);
886}
887static inline bool DescendingPlaneSort(const HeightFieldPlane * const A, const HeightFieldPlane * const B)
888{
889 return ((A->maxAAAB - B->maxAAAB) > dEpsilon);
890}
891
892void dxHeightfield::sortPlanes(const size_t numPlanes)
893{
894 bool has_swapped = true;
895 do
896 {
897 has_swapped = false;//reset flag
898 for (size_t i = 0; i < numPlanes - 1; i++)
899 {
900 //if they are in the wrong order
901 if (DescendingPlaneSort(tempPlaneBuffer[i], tempPlaneBuffer[i + 1]))
902 {
903 //exchange them
904 HeightFieldPlane * tempPlane = tempPlaneBuffer[i];
905 tempPlaneBuffer[i] = tempPlaneBuffer[i + 1];
906 tempPlaneBuffer[i + 1] = tempPlane;
907
908 //we have swapped at least once, list may not be sorted yet
909 has_swapped = true;
910 }
911 }
912 } //if no swaps were made during this pass, the list has been sorted
913 while (has_swapped);
914}
915
916static inline dReal DistancePointToLine(const dVector3 &_point,
917 const dVector3 &_pt0,
918 const dVector3 &_Edge,
919 const dReal _Edgelength)
920{
921 dVector3 v;
922 dVector3Subtract(_point, _pt0, v);
923 dVector3 s;
924 dVector3Copy (_Edge, s);
925 const dReal dot = dVector3Dot(v, _Edge) / _Edgelength;
926 dVector3Scale(s, dot);
927 dVector3Subtract(v, s, v);
928 return dVector3Length(v);
929}
930
931
932
933
934int dxHeightfield::dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ,
935 dxGeom* o2, const int numMaxContactsPossible,
936 int flags, dContactGeom* contact,
937 int skip )
938{
939 dContactGeom *pContact = 0;
940 int x, z;
941 // check if not above or inside terrain first
942 // while filling a heightmap partial temporary buffer
943 const unsigned int numX = (maxX - minX) + 1;
944 const unsigned int numZ = (maxZ - minZ) + 1;
945 const dReal minO2Height = o2->aabb[2];
946 const dReal maxO2Height = o2->aabb[3];
947 unsigned int x_local, z_local;
948 dReal maxY = - dInfinity;
949 dReal minY = dInfinity;
950 // localize and const for faster access
951 const dReal cfSampleWidth = m_p_data->m_fSampleWidth;
952 const dReal cfSampleDepth = m_p_data->m_fSampleDepth;
953 {
954 if (tempHeightBufferSizeX < numX || tempHeightBufferSizeZ < numZ)
955 {
956 resetHeightBuffer();
957 allocateHeightBuffer(numX, numZ);
958 }
959
960 dReal Xpos, Ypos;
961 Xpos = minX * cfSampleWidth;
962
963
964 for ( x = minX, x_local = 0; x_local < numX; x++, x_local++)
965 {
966 const dReal c_Xpos = Xpos;
967 HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local];
968 Ypos = minZ * cfSampleDepth;
969 for ( z = minZ, z_local = 0; z_local < numZ; z++, z_local++)
970 {
971 const dReal h = m_p_data->GetHeight(x, z);
972 HeightFieldRow[z_local].vertex[0] = c_Xpos;
973 HeightFieldRow[z_local].vertex[1] = h;
974 HeightFieldRow[z_local].vertex[2] = Ypos;
975
976
977 maxY = dMAX(maxY, h);
978 minY = dMIN(minY, h);
979
980
981 Ypos += cfSampleDepth;
982 }
983 Xpos += cfSampleWidth;
984 }
985 if (minO2Height - maxY > -dEpsilon )
986 {
987 //totally above heightfield
988 return 0;
989 }
990 if (minY - maxO2Height > -dEpsilon )
991 {
992 // totally under heightfield
993 pContact = CONTACT(contact, 0);
994
995 pContact->pos[0] = o2->final_posr->pos[0];
996 pContact->pos[1] = minY;
997 pContact->pos[2] = o2->final_posr->pos[2];
998
999 pContact->normal[0] = 0;
1000 pContact->normal[1] = - 1;
1001 pContact->normal[2] = 0;
1002
1003 pContact->depth = minY - maxO2Height;
1004
1005 return 1;
1006 }
1007 }
1008 // get All Planes that could collide against.
1009 dColliderFn *geomRayNCollider;
1010 dColliderFn *geomNPlaneCollider;
1011 dGetDepthFn *geomNDepthGetter;
1012
1013 // int max_collisionContact = numMaxContactsPossible; -- not used
1014 switch (o2->type)
1015 {
1016 case dRayClass:
1017 geomRayNCollider = NULL;
1018 geomNPlaneCollider = dCollideRayPlane;
1019 geomNDepthGetter = NULL;
1020 //max_collisionContact = 1;
1021 break;
1022
1023 case dSphereClass:
1024 geomRayNCollider = dCollideRaySphere;
1025 geomNPlaneCollider = dCollideSpherePlane;
1026 geomNDepthGetter = dGeomSpherePointDepth;
1027 //max_collisionContact = 3;
1028 break;
1029
1030 case dBoxClass:
1031 geomRayNCollider = dCollideRayBox;
1032 geomNPlaneCollider = dCollideBoxPlane;
1033 geomNDepthGetter = dGeomBoxPointDepth;
1034 //max_collisionContact = 8;
1035 break;
1036
1037 case dCapsuleClass:
1038 geomRayNCollider = dCollideRayCapsule;
1039 geomNPlaneCollider = dCollideCapsulePlane;
1040 geomNDepthGetter = dGeomCapsulePointDepth;
1041 // max_collisionContact = 3;
1042 break;
1043
1044 case dCylinderClass:
1045 geomRayNCollider = dCollideRayCylinder;
1046 geomNPlaneCollider = dCollideCylinderPlane;
1047 geomNDepthGetter = NULL;// TODO: dGeomCCylinderPointDepth
1048 //max_collisionContact = 3;
1049 break;
1050
1051 case dConvexClass:
1052 geomRayNCollider = dCollideRayConvex;
1053 geomNPlaneCollider = dCollideConvexPlane;
1054 geomNDepthGetter = NULL;// TODO: dGeomConvexPointDepth;
1055 //max_collisionContact = 3;
1056 break;
1057
1058#if dTRIMESH_ENABLED
1059
1060 case dTriMeshClass:
1061 geomRayNCollider = dCollideRayTrimesh;
1062 geomNPlaneCollider = dCollideTrimeshPlane;
1063 geomNDepthGetter = NULL;// TODO: dGeomTrimeshPointDepth;
1064 //max_collisionContact = 3;
1065 break;
1066
1067#endif // dTRIMESH_ENABLED
1068
1069 default:
1070 dIASSERT(0); // Shouldn't ever get here.
1071 break;
1072
1073 }
1074
1075 dxPlane myplane(0,0,0,0,0);
1076 dxPlane* sliding_plane = &myplane;
1077 dReal triplane[4];
1078 int i;
1079
1080 // check some trivial case.
1081 // Vector Up plane
1082 if (maxY - minY < dEpsilon)
1083 {
1084 // it's a single plane.
1085 triplane[0] = 0;
1086 triplane[1] = 1;
1087 triplane[2] = 0;
1088 triplane[3] = minY;
1089 dGeomPlaneSetNoNormalize (sliding_plane, triplane);
1090 // find collision and compute contact points
1091 const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip);
1092 dIASSERT(numTerrainContacts <= numMaxContactsPossible);
1093 for (i = 0; i < numTerrainContacts; i++)
1094 {
1095 pContact = CONTACT(contact, i*skip);
1096 dOPESIGN(pContact->normal, =, -, triplane);
1097 }
1098 return numTerrainContacts;
1099 }
1100 // unique plane
1101 {
1102 // check for very simple plane heightfield
1103 dReal minXHeightDelta = dInfinity, maxXHeightDelta = - dInfinity;
1104 dReal minZHeightDelta = dInfinity, maxZHeightDelta = - dInfinity;
1105
1106
1107 dReal lastXHeight = tempHeightBuffer[0][0].vertex[1];
1108 for ( x_local = 1; x_local < numX; x_local++)
1109 {
1110 HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local];
1111
1112 const dReal deltaX = HeightFieldRow[0].vertex[1] - lastXHeight;
1113
1114 maxXHeightDelta = dMAX (maxXHeightDelta, deltaX);
1115 minXHeightDelta = dMIN (minXHeightDelta, deltaX);
1116
1117 dReal lastZHeight = HeightFieldRow[0].vertex[1];
1118 for ( z_local = 1; z_local < numZ; z_local++)
1119 {
1120 const dReal deltaZ = (HeightFieldRow[z_local].vertex[1] - lastZHeight);
1121
1122 maxZHeightDelta = dMAX (maxZHeightDelta, deltaZ);
1123 minZHeightDelta = dMIN (minZHeightDelta, deltaZ);
1124
1125 }
1126 }
1127
1128 if (maxZHeightDelta - minZHeightDelta < dEpsilon &&
1129 maxXHeightDelta - minXHeightDelta < dEpsilon )
1130 {
1131 // it's a single plane.
1132 const dVector3 &A = tempHeightBuffer[0][0].vertex;
1133 const dVector3 &B = tempHeightBuffer[1][0].vertex;
1134 const dVector3 &C = tempHeightBuffer[0][1].vertex;
1135
1136 // define 2 edges and a point that will define collision plane
1137 {
1138 dVector3 Edge1, Edge2;
1139 dVector3Subtract(C, A, Edge1);
1140 dVector3Subtract(B, A, Edge2);
1141 dVector3Cross(Edge1, Edge2, triplane);
1142 }
1143
1144 // Define Plane
1145 // Normalize plane normal
1146 const dReal dinvlength = REAL(1.0) / dVector3Length(triplane);
1147 triplane[0] *= dinvlength;
1148 triplane[1] *= dinvlength;
1149 triplane[2] *= dinvlength;
1150 // get distance to origin from plane
1151 triplane[3] = dVector3Dot(triplane, A);
1152
1153 dGeomPlaneSetNoNormalize (sliding_plane, triplane);
1154 // find collision and compute contact points
1155 const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip);
1156 dIASSERT(numTerrainContacts <= numMaxContactsPossible);
1157 for (i = 0; i < numTerrainContacts; i++)
1158 {
1159 pContact = CONTACT(contact, i*skip);
1160 dOPESIGN(pContact->normal, =, -, triplane);
1161 }
1162 return numTerrainContacts;
1163 }
1164 }
1165
1166
1167 int numTerrainContacts = 0;
1168 dContactGeom *PlaneContact = m_p_data->m_contacts;
1169
1170 const unsigned int numTriMax = (maxX - minX) * (maxZ - minZ) * 2;
1171 if (tempTriangleBufferSize < numTriMax)
1172 {
1173 resetTriangleBuffer();
1174 allocateTriangleBuffer(numTriMax);
1175 }
1176
1177 // Sorting triangle/plane resulting from heightfield zone
1178 // Perhaps that would be necessary in case of too much limited
1179 // maximum contact point...
1180 // or in complex mesh case (trimesh and convex)
1181 // need some test or insights on this before enabling this.
1182 const bool isContactNumPointsLimited =
1183 true;
1184 // (numMaxContacts < 8)
1185 // || o2->type == dConvexClass
1186 // || o2->type == dTriMeshClass
1187 // || (numMaxContacts < (int)numTriMax)
1188
1189
1190
1191 // if small heightfield triangle related to O2 colliding
1192 // or no Triangle colliding at all.
1193 bool needFurtherPasses = (o2->type == dTriMeshClass);
1194 //compute Ratio between Triangle size and O2 aabb size
1195 // no FurtherPasses are needed in ray class
1196 if (o2->type != dRayClass && needFurtherPasses == false)
1197 {
1198 const dReal xratio = (o2->aabb[1] - o2->aabb[0]) * m_p_data->m_fInvSampleWidth;
1199 if (xratio > REAL(1.5))
1200 needFurtherPasses = true;
1201 else
1202 {
1203 const dReal zratio = (o2->aabb[5] - o2->aabb[4]) * m_p_data->m_fInvSampleDepth;
1204 if (zratio > REAL(1.5))
1205 needFurtherPasses = true;
1206 }
1207
1208 }
1209
1210 unsigned int numTri = 0;
1211 HeightFieldVertex *A, *B, *C, *D;
1212 /* (y is up)
1213 A--------B-...x
1214 | /|
1215 | / |
1216 | / |
1217 | / |
1218 | / |
1219 | / |
1220 | / |
1221 |/ |
1222 C--------D
1223 .
1224 .
1225 .
1226 z
1227 */
1228 // keep only triangle that does intersect geom
1229 for ( x = minX, x_local = 0; x < maxX; x++, x_local++)
1230 {
1231 HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local];
1232 HeightFieldVertex *HeightFieldNextRow = tempHeightBuffer[x_local + 1];
1233
1234 // First A
1235 C = &HeightFieldRow [0];
1236 // First B
1237 D = &HeightFieldNextRow[0];
1238 for ( z = minZ, z_local = 0; z < maxZ; z++, z_local++)
1239 {
1240 A = C;
1241 B = D;
1242
1243 C = &HeightFieldRow [z_local + 1];
1244 D = &HeightFieldNextRow[z_local + 1];
1245
1246 const dReal AHeight = A->vertex[1];
1247 const dReal BHeight = B->vertex[1];
1248 const dReal CHeight = C->vertex[1];
1249 const dReal DHeight = D->vertex[1];
1250
1251 const bool isACollide = 0 < AHeight - minO2Height;
1252 const bool isBCollide = 0 < BHeight - minO2Height;
1253 const bool isCCollide = 0 < CHeight - minO2Height;
1254 const bool isDCollide = 0 < DHeight - minO2Height;
1255
1256 A->state = !(isACollide);
1257 B->state = !(isBCollide);
1258 C->state = !(isCCollide);
1259 D->state = !(isCCollide);
1260
1261 if (isACollide || isBCollide || isCCollide)
1262 {
1263 HeightFieldTriangle * const CurrTriUp = &tempTriangleBuffer[numTri++];
1264
1265 CurrTriUp->state = false;
1266
1267 // changing point order here implies to change it in isOnHeightField
1268 CurrTriUp->vertices[0] = A;
1269 CurrTriUp->vertices[1] = B;
1270 CurrTriUp->vertices[2] = C;
1271
1272 if (isContactNumPointsLimited)
1273 CurrTriUp->setMinMax();
1274 CurrTriUp->isUp = true;
1275 }
1276
1277 if (isBCollide || isCCollide || isDCollide)
1278 {
1279 HeightFieldTriangle * const CurrTriDown = &tempTriangleBuffer[numTri++];
1280
1281 CurrTriDown->state = false;
1282 // changing point order here implies to change it in isOnHeightField
1283
1284 CurrTriDown->vertices[0] = D;
1285 CurrTriDown->vertices[1] = B;
1286 CurrTriDown->vertices[2] = C;
1287
1288
1289 if (isContactNumPointsLimited)
1290 CurrTriDown->setMinMax();
1291 CurrTriDown->isUp = false;
1292 }
1293
1294
1295 if (needFurtherPasses &&
1296 (isBCollide || isCCollide)
1297 &&
1298 (AHeight - CHeight > 0 &&
1299 AHeight - BHeight > 0 &&
1300 DHeight - CHeight > 0 &&
1301 DHeight - BHeight > 0))
1302 {
1303 // That means Edge BC is concave, therefore
1304 // BC Edge and B and C vertices cannot collide
1305
1306 B->state = true;
1307 C->state = true;
1308 }
1309 // should find a way to check other edges (AB, BD, CD) too for concavity
1310 }
1311 }
1312
1313 // at least on triangle should intersect geom
1314 dIASSERT (numTri != 0);
1315 // pass1: VS triangle as Planes
1316 // Group Triangle by same plane definition
1317 // as Terrain often has many triangles using same plane definition
1318 // then collide against that list of triangles.
1319 {
1320
1321 dVector3 Edge1, Edge2;
1322 //compute all triangles normals.
1323 for (unsigned int k = 0; k < numTri; k++)
1324 {
1325 HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
1326
1327 // define 2 edges and a point that will define collision plane
1328 dVector3Subtract(itTriangle->vertices[2]->vertex, itTriangle->vertices[0]->vertex, Edge1);
1329 dVector3Subtract(itTriangle->vertices[1]->vertex, itTriangle->vertices[0]->vertex, Edge2);
1330
1331 // find a perpendicular vector to the triangle
1332 if (itTriangle->isUp)
1333 dVector3Cross(Edge1, Edge2, triplane);
1334 else
1335 dVector3Cross(Edge2, Edge1, triplane);
1336
1337 // Define Plane
1338 // Normalize plane normal
1339 const dReal dinvlength = REAL(1.0) / dVector3Length(triplane);
1340 triplane[0] *= dinvlength;
1341 triplane[1] *= dinvlength;
1342 triplane[2] *= dinvlength;
1343 // get distance to origin from plane
1344 triplane[3] = dVector3Dot(triplane, itTriangle->vertices[0]->vertex);
1345
1346 // saves normal for collision check (planes, triangles, vertices and edges.)
1347 dVector3Copy(triplane, itTriangle->planeDef);
1348 // saves distance for collision check (planes, triangles, vertices and edges.)
1349 itTriangle->planeDef[3] = triplane[3];
1350 }
1351
1352 // group by Triangles by Planes sharing shame plane definition
1353 if (tempPlaneBufferSize < numTri)
1354 {
1355 resetPlaneBuffer();
1356 allocatePlaneBuffer(numTri);
1357 }
1358 unsigned int numPlanes = 0;
1359 for (unsigned int k = 0; k < numTri; k++)
1360 {
1361 HeightFieldTriangle * const tri_base = &tempTriangleBuffer[k];
1362
1363 if (tri_base->state == true)
1364 continue;// already tested or added to plane list.
1365
1366 HeightFieldPlane * const currPlane = tempPlaneBuffer[numPlanes];
1367 currPlane->resetTriangleListSize(numTri - k);
1368 currPlane->addTriangle(tri_base);
1369 // saves normal for collision check (planes, triangles, vertices and edges.)
1370 dVector3Copy(tri_base->planeDef, currPlane->planeDef);
1371 // saves distance for collision check (planes, triangles, vertices and edges.)
1372 currPlane->planeDef[3]= tri_base->planeDef[3];
1373
1374 const dReal normx = tri_base->planeDef[0];
1375 const dReal normy = tri_base->planeDef[1];
1376 const dReal normz = tri_base->planeDef[2];
1377 const dReal dist = tri_base->planeDef[3];
1378
1379 for (unsigned int m = k + 1; m < numTri; m++)
1380 {
1381
1382 HeightFieldTriangle * const tri_test = &tempTriangleBuffer[m];
1383 if (tri_test->state == true)
1384 continue;// already tested or added to plane list.
1385
1386 // normals and distance are the same.
1387 if (
1388 dFabs(normy - tri_test->planeDef[1]) < dEpsilon &&
1389 dFabs(dist - tri_test->planeDef[3]) < dEpsilon &&
1390 dFabs(normx - tri_test->planeDef[0]) < dEpsilon &&
1391 dFabs(normz - tri_test->planeDef[2]) < dEpsilon
1392 )
1393 {
1394 currPlane->addTriangle (tri_test);
1395 tri_test->state = true;
1396 }
1397 }
1398
1399 tri_base->state = true;
1400 if (isContactNumPointsLimited)
1401 currPlane->setMinMax();
1402
1403 numPlanes++;
1404 }
1405
1406 // sort planes
1407 if (isContactNumPointsLimited)
1408 sortPlanes(numPlanes);
1409
1410#if !defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
1411 /*
1412 Note by Oleh_Derevenko:
1413 It seems to be incorrect to limit contact count by some particular value
1414 since some of them (and even all of them) may be culled in following condition.
1415 However I do not see an easy way to fix this.
1416 If not that culling the flags modification should be changed here and
1417 additionally repeated after some contacts have been generated (in "if (didCollide)").
1418 The maximum of contacts in flags would then be set to minimum of contacts
1419 remaining and HEIGHTFIELDMAXCONTACTPERCELL.
1420 */
1421 int planeTestFlags = (flags & ~NUMC_MASK) | HEIGHTFIELDMAXCONTACTPERCELL;
1422 dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
1423#else // if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
1424 int numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
1425 int planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane;
1426 dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
1427#endif
1428
1429 for (unsigned int k = 0; k < numPlanes; k++)
1430 {
1431 HeightFieldPlane * const itPlane = tempPlaneBuffer[k];
1432
1433 //set Geom
1434 dGeomPlaneSetNoNormalize (sliding_plane, itPlane->planeDef);
1435 //dGeomPlaneSetParams (sliding_plane, triangle_Plane[0], triangle_Plane[1], triangle_Plane[2], triangle_Plane[3]);
1436 // find collision and compute contact points
1437 bool didCollide = false;
1438 const int numPlaneContacts = geomNPlaneCollider (o2, sliding_plane, planeTestFlags, PlaneContact, sizeof(dContactGeom));
1439 const size_t planeTriListSize = itPlane->trianglelistCurrentSize;
1440 for (i = 0; i < numPlaneContacts; i++)
1441 {
1442 // Check if contact point found in plane is inside Triangle.
1443 const dVector3 &pCPos = PlaneContact[i].pos;
1444 for (size_t b = 0; planeTriListSize > b; b++)
1445 {
1446 if (m_p_data->IsOnHeightfield2 (itPlane->trianglelist[b]->vertices[0]->vertex,
1447 pCPos,
1448 itPlane->trianglelist[b]->isUp))
1449 {
1450 pContact = CONTACT(contact, numTerrainContacts*skip);
1451 dVector3Copy(pCPos, pContact->pos);
1452 dOPESIGN(pContact->normal, =, -, itPlane->planeDef);
1453 pContact->depth = PlaneContact[i].depth;
1454 numTerrainContacts++;
1455 if ( numTerrainContacts == numMaxContactsPossible )
1456 return numTerrainContacts;
1457
1458 didCollide = true;
1459 break;
1460 }
1461 }
1462 }
1463 if (didCollide)
1464 {
1465#if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
1466 /* Note by Oleh_Derevenko:
1467 This code is not used - see another note above
1468 */
1469 numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
1470 planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane;
1471 dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
1472#endif
1473 for (size_t b = 0; planeTriListSize > b; b++)
1474 {
1475 // flag Triangles Vertices as collided
1476 // to prevent any collision test of those
1477 for (i = 0; i < 3; i++)
1478 itPlane->trianglelist[b]->vertices[i]->state = true;
1479 }
1480 }
1481 else
1482 {
1483 // flag triangle as not collided so that Vertices or Edge
1484 // of that triangles will be checked.
1485 for (size_t b = 0; planeTriListSize > b; b++)
1486 {
1487 itPlane->trianglelist[b]->state = false;
1488 }
1489 }
1490 }
1491 }
1492
1493
1494
1495 // pass2: VS triangle vertices
1496 if (needFurtherPasses)
1497 {
1498 dxRay tempRay(0, 1);
1499 dReal depth;
1500 bool vertexCollided;
1501
1502 // Only one contact is necessary for ray test
1503 int rayTestFlags = (flags & ~NUMC_MASK) | 1;
1504 dIASSERT((1 & ~NUMC_MASK) == 0);
1505 //
1506 // Find Contact Penetration Depth of each vertices
1507 //
1508 for (unsigned int k = 0; k < numTri; k++)
1509 {
1510 const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
1511 if (itTriangle->state == true)
1512 continue;// plane triangle did already collide.
1513
1514 for (size_t i = 0; i < 3; i++)
1515 {
1516 HeightFieldVertex *vertex = itTriangle->vertices[i];
1517 if (vertex->state == true)
1518 continue;// vertice did already collide.
1519
1520 vertexCollided = false;
1521 const dVector3 &triVertex = vertex->vertex;
1522 if ( geomNDepthGetter )
1523 {
1524 depth = geomNDepthGetter( o2,
1525 triVertex[0], triVertex[1], triVertex[2] );
1526 if (depth + dEpsilon < 0)
1527 vertexCollided = true;
1528 }
1529 else
1530 {
1531 // We don't have a GetDepth function, so do a ray cast instead.
1532 // NOTE: This isn't ideal, and a GetDepth function should be
1533 // written for all geom classes.
1534 tempRay.length = (minO2Height - triVertex[1]) * REAL(1000.0);
1535
1536 //dGeomRaySet( &tempRay, pContact->pos[0], pContact->pos[1], pContact->pos[2],
1537 // - itTriangle->Normal[0], - itTriangle->Normal[1], - itTriangle->Normal[2] );
1538 dGeomRaySetNoNormalize(tempRay, triVertex, itTriangle->planeDef);
1539
1540 if ( geomRayNCollider( &tempRay, o2, rayTestFlags, PlaneContact, sizeof( dContactGeom ) ) )
1541 {
1542 depth = PlaneContact[0].depth;
1543 vertexCollided = true;
1544 }
1545 }
1546 if (vertexCollided)
1547 {
1548 pContact = CONTACT(contact, numTerrainContacts*skip);
1549 //create contact using vertices
1550 dVector3Copy (triVertex, pContact->pos);
1551 //create contact using Plane Normal
1552 dOPESIGN(pContact->normal, =, -, itTriangle->planeDef);
1553
1554 pContact->depth = depth;
1555
1556 numTerrainContacts++;
1557 if ( numTerrainContacts == numMaxContactsPossible )
1558 return numTerrainContacts;
1559
1560 vertex->state = true;
1561 }
1562 }
1563 }
1564 }
1565
1566#ifdef _HEIGHTFIELDEDGECOLLIDING
1567 // pass3: VS triangle Edges
1568 if (needFurtherPasses)
1569 {
1570 dVector3 Edge;
1571 dxRay edgeRay(0, 1);
1572
1573 int numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
1574 int triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri;
1575 dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
1576
1577 for (unsigned int k = 0; k < numTri; k++)
1578 {
1579 const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
1580
1581 if (itTriangle->state == true)
1582 continue;// plane did already collide.
1583
1584 for (size_t m = 0; m < 3; m++)
1585 {
1586 const size_t next = (m + 1) % 3;
1587 HeightFieldVertex *vertex0 = itTriangle->vertices[m];
1588 HeightFieldVertex *vertex1 = itTriangle->vertices[next];
1589
1590 // not concave or under the AABB
1591 // nor triangle already collided against vertices
1592 if (vertex0->state == true && vertex1->state == true)
1593 continue;// plane did already collide.
1594
1595 dVector3Subtract(vertex1->vertex, vertex0->vertex, Edge);
1596 edgeRay.length = dVector3Length (Edge);
1597 dGeomRaySetNoNormalize(edgeRay, vertex1->vertex, Edge);
1598 int prevTerrainContacts = numTerrainContacts;
1599 pContact = CONTACT(contact, prevTerrainContacts*skip);
1600 const int numCollision = geomRayNCollider(&edgeRay,o2,triTestFlags,pContact,skip);
1601 dIASSERT(numCollision <= numMaxContactsPerTri);
1602
1603 if (numCollision)
1604 {
1605 numTerrainContacts += numCollision;
1606
1607 do
1608 {
1609 pContact = CONTACT(contact, prevTerrainContacts*skip);
1610
1611 //create contact using Plane Normal
1612 dOPESIGN(pContact->normal, =, -, itTriangle->planeDef);
1613
1614 pContact->depth = DistancePointToLine(pContact->pos, vertex1->vertex, Edge, edgeRay.length);
1615 }
1616 while (++prevTerrainContacts != numTerrainContacts);
1617
1618 if ( numTerrainContacts == numMaxContactsPossible )
1619 return numTerrainContacts;
1620
1621 numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
1622 triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri;
1623 dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
1624 }
1625 }
1626
1627 itTriangle->vertices[0]->state = true;
1628 itTriangle->vertices[1]->state = true;
1629 itTriangle->vertices[2]->state = true;
1630 }
1631 }
1632#endif // _HEIGHTFIELDEDGECOLLIDING
1633 return numTerrainContacts;
1634}
1635
1636int dCollideHeightfield( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contact, int skip )
1637{
1638 dIASSERT( skip >= (int)sizeof(dContactGeom) );
1639 dIASSERT( o1->type == dHeightfieldClass );
1640 dIASSERT((flags & NUMC_MASK) >= 1);
1641
1642 int i;
1643
1644 // if ((flags & NUMC_MASK) == 0) -- An assertion check is made on entry
1645 // { flags = (flags & ~NUMC_MASK) | 1; dIASSERT((1 & ~NUMC_MASK) == 0); }
1646
1647 int numMaxTerrainContacts = (flags & NUMC_MASK);
1648
1649 dxHeightfield *terrain = (dxHeightfield*) o1;
1650
1651 dVector3 posbak;
1652 dMatrix3 Rbak;
1653 dReal aabbbak[6];
1654 int gflagsbak;
1655 dVector3 pos0,pos1;
1656 dMatrix3 R1;
1657
1658 int numTerrainContacts = 0;
1659
1660 //@@ Should find a way to set reComputeAABB to false in default case
1661 // aka DHEIGHTFIELD_CORNER_ORIGIN not defined and terrain not PLACEABLE
1662 // so that we can free some memory and speed up things a bit
1663 // while saving some precision loss
1664#ifndef DHEIGHTFIELD_CORNER_ORIGIN
1665 const bool reComputeAABB = true;
1666#else
1667 const bool reComputeAABB = ( terrain->gflags & GEOM_PLACEABLE ) ? true : false;
1668#endif //DHEIGHTFIELD_CORNER_ORIGIN
1669
1670 //
1671 // Transform O2 into Heightfield Space
1672 //
1673 if (reComputeAABB)
1674 {
1675 // Backup original o2 position, rotation and AABB.
1676 dVector3Copy( o2->final_posr->pos, posbak );
1677 dMatrix3Copy( o2->final_posr->R, Rbak );
1678 memcpy( aabbbak, o2->aabb, sizeof( dReal ) * 6 );
1679 gflagsbak = o2->gflags;
1680 }
1681
1682 if ( terrain->gflags & GEOM_PLACEABLE )
1683 {
1684 // Transform o2 into heightfield space.
1685 dOP( pos0, -, o2->final_posr->pos, terrain->final_posr->pos );
1686 dMULTIPLY1_331( pos1, terrain->final_posr->R, pos0 );
1687 dMULTIPLY1_333( R1, terrain->final_posr->R, o2->final_posr->R );
1688
1689 // Update o2 with transformed position and rotation.
1690 dVector3Copy( pos1, o2->final_posr->pos );
1691 dMatrix3Copy( R1, o2->final_posr->R );
1692 }
1693
1694#ifndef DHEIGHTFIELD_CORNER_ORIGIN
1695 o2->final_posr->pos[ 0 ] += terrain->m_p_data->m_fHalfWidth;
1696 o2->final_posr->pos[ 2 ] += terrain->m_p_data->m_fHalfDepth;
1697#endif // DHEIGHTFIELD_CORNER_ORIGIN
1698
1699 // Rebuild AABB for O2
1700 if (reComputeAABB)
1701 o2->computeAABB();
1702
1703 //
1704 // Collide
1705 //
1706
1707 //check if inside boundaries
1708 // using O2 aabb
1709 // aabb[6] is (minx, maxx, miny, maxy, minz, maxz)
1710 const bool wrapped = terrain->m_p_data->m_bWrapMode != 0;
1711
1712 int nMinX;
1713 int nMaxX;
1714 int nMinZ;
1715 int nMaxZ;
1716
1717 if ( !wrapped )
1718 {
1719 if ( o2->aabb[0] > terrain->m_p_data->m_fWidth //MinX
1720 && o2->aabb[4] > terrain->m_p_data->m_fDepth)//MinZ
1721 goto dCollideHeightfieldExit;
1722
1723 if ( o2->aabb[1] < 0 //MaxX
1724 && o2->aabb[5] < 0) //MaxZ
1725 goto dCollideHeightfieldExit;
1726
1727 }
1728
1729 nMinX = int(dFloor(o2->aabb[0] * terrain->m_p_data->m_fInvSampleWidth));
1730 nMaxX = int(dFloor(o2->aabb[1] * terrain->m_p_data->m_fInvSampleWidth)) + 1;
1731 nMinZ = int(dFloor(o2->aabb[4] * terrain->m_p_data->m_fInvSampleDepth));
1732 nMaxZ = int(dFloor(o2->aabb[5] * terrain->m_p_data->m_fInvSampleDepth)) + 1;
1733
1734 if ( !wrapped )
1735 {
1736 nMinX = dMAX( nMinX, 0 );
1737 nMaxX = dMIN( nMaxX, terrain->m_p_data->m_nWidthSamples - 1 );
1738 nMinZ = dMAX( nMinZ, 0 );
1739 nMaxZ = dMIN( nMaxZ, terrain->m_p_data->m_nDepthSamples - 1 );
1740
1741 dIASSERT ((nMinX < nMaxX) || (nMinZ < nMaxZ))
1742 }
1743
1744
1745
1746 numTerrainContacts += terrain->dCollideHeightfieldZone(
1747 nMinX,nMaxX,nMinZ,nMaxZ,o2,numMaxTerrainContacts - numTerrainContacts,
1748 flags,CONTACT(contact,numTerrainContacts*skip),skip );
1749
1750 dIASSERT( numTerrainContacts <= numMaxTerrainContacts );
1751
1752 dContactGeom *pContact;
1753 for ( i = 0; i < numTerrainContacts; ++i )
1754 {
1755 pContact = CONTACT(contact,i*skip);
1756 pContact->g1 = o1;
1757 pContact->g2 = o2;
1758 }
1759
1760
1761 //------------------------------------------------------------------------------
1762
1763dCollideHeightfieldExit:
1764
1765 if (reComputeAABB)
1766 {
1767 // Restore o2 position, rotation and AABB
1768 dVector3Copy( posbak, o2->final_posr->pos );
1769 dMatrix3Copy( Rbak, o2->final_posr->R );
1770 memcpy( o2->aabb, aabbbak, sizeof(dReal)*6 );
1771 o2->gflags = gflagsbak;
1772
1773 //
1774 // Transform Contacts to World Space
1775 //
1776 if ( terrain->gflags & GEOM_PLACEABLE )
1777 {
1778 for ( i = 0; i < numTerrainContacts; ++i )
1779 {
1780 pContact = CONTACT(contact,i*skip);
1781 dOPE( pos0, =, pContact->pos );
1782
1783#ifndef DHEIGHTFIELD_CORNER_ORIGIN
1784 pos0[ 0 ] -= terrain->m_p_data->m_fHalfWidth;
1785 pos0[ 2 ] -= terrain->m_p_data->m_fHalfDepth;
1786#endif // !DHEIGHTFIELD_CORNER_ORIGIN
1787
1788 dMULTIPLY0_331( pContact->pos, terrain->final_posr->R, pos0 );
1789
1790 dOP( pContact->pos, +, pContact->pos, terrain->final_posr->pos );
1791 dOPE( pos0, =, pContact->normal );
1792
1793 dMULTIPLY0_331( pContact->normal, terrain->final_posr->R, pos0 );
1794 }
1795 }
1796#ifndef DHEIGHTFIELD_CORNER_ORIGIN
1797 else
1798 {
1799 for ( i = 0; i < numTerrainContacts; ++i )
1800 {
1801 pContact = CONTACT(contact,i*skip);
1802 pContact->pos[ 0 ] -= terrain->m_p_data->m_fHalfWidth;
1803 pContact->pos[ 2 ] -= terrain->m_p_data->m_fHalfDepth;
1804 }
1805 }
1806#endif // !DHEIGHTFIELD_CORNER_ORIGIN
1807 }
1808 // Return contact count.
1809 return numTerrainContacts;
1810}
1811
1812
diff --git a/libraries/ode-0.9/ode/src/heightfield.h b/libraries/ode-0.9/ode/src/heightfield.h
deleted file mode 100644
index f4c5952..0000000
--- a/libraries/ode-0.9/ode/src/heightfield.h
+++ /dev/null
@@ -1,225 +0,0 @@
1// dHeightfield Collider
2// Martijn Buijs 2006 http://home.planet.nl/~buijs512/
3// Based on Terrain & Cone contrib by:
4// Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
5
6#ifndef _DHEIGHTFIELD_H_
7#define _DHEIGHTFIELD_H_
8//------------------------------------------------------------------------------
9
10#include <ode/common.h>
11#include "collision_kernel.h"
12
13
14#define HEIGHTFIELDMAXCONTACTPERCELL 10
15
16//
17// dxHeightfieldData
18//
19// Heightfield Data structure
20//
21struct dxHeightfieldData
22{
23 dReal m_fWidth; // World space heightfield dimension on X axis
24 dReal m_fDepth; // World space heightfield dimension on Z axis
25 dReal m_fSampleWidth; // Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
26 dReal m_fSampleDepth; // Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
27 dReal m_fInvSampleWidth; // Cache of inverse Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
28 dReal m_fInvSampleDepth; // Cache of inverse Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
29
30 dReal m_fHalfWidth; // Cache of half of m_fWidth
31 dReal m_fHalfDepth; // Cache of half of m_fDepth
32
33 dReal m_fMinHeight; // Min sample height value (scaled and offset)
34 dReal m_fMaxHeight; // Max sample height value (scaled and offset)
35 dReal m_fThickness; // Surface thickness (added to bottom AABB)
36 dReal m_fScale; // Sample value multiplier
37 dReal m_fOffset; // Vertical sample offset
38
39 int m_nWidthSamples; // Vertex count on X axis edge (number of samples)
40 int m_nDepthSamples; // Vertex count on Z axis edge (number of samples)
41 int m_bCopyHeightData; // Do we own the sample data?
42 int m_bWrapMode; // Heightfield wrapping mode (0=finite, 1=infinite)
43 int m_nGetHeightMode; // GetHeight mode ( 0=callback, 1=byte, 2=short, 3=float )
44
45 const void* m_pHeightData; // Sample data array
46 void* m_pUserData; // Callback user data
47
48 dContactGeom m_contacts[HEIGHTFIELDMAXCONTACTPERCELL];
49
50 dHeightfieldGetHeight* m_pGetHeightCallback; // Callback pointer.
51
52 dxHeightfieldData();
53 ~dxHeightfieldData();
54
55 void SetData( int nWidthSamples, int nDepthSamples,
56 dReal fWidth, dReal fDepth,
57 dReal fScale, dReal fOffset,
58 dReal fThickness, int bWrapMode );
59
60 void ComputeHeightBounds();
61
62 bool IsOnHeightfield ( const dReal * const CellOrigin, const dReal * const pos, const bool isABC) const;
63 bool IsOnHeightfield2 ( const dReal * const CellOrigin, const dReal * const pos, const bool isABC) const;
64
65 dReal GetHeight(int x, int z);
66 dReal GetHeight(dReal x, dReal z);
67
68};
69
70class HeightFieldVertex;
71class HeightFieldEdge;
72class HeightFieldTriangle;
73
74class HeightFieldVertex
75{
76public:
77 HeightFieldVertex(){};
78
79 dVector3 vertex;
80 bool state;
81};
82
83class HeightFieldEdge
84{
85public:
86 HeightFieldEdge(){};
87
88 HeightFieldVertex *vertices[2];
89};
90//
91// HeightFieldTriangle
92//
93// HeightFieldTriangle composing heightfield mesh
94//
95class HeightFieldTriangle
96{
97public:
98 HeightFieldTriangle(){};
99
100 inline void setMinMax()
101 {
102 maxAAAB = vertices[0]->vertex[1] > vertices[1]->vertex[1] ? vertices[0]->vertex[1] : vertices[1]->vertex[1];
103 maxAAAB = vertices[2]->vertex[1] > maxAAAB ? vertices[2]->vertex[1] : maxAAAB;
104 };
105
106 HeightFieldVertex *vertices[3];
107 dReal planeDef[4];
108 dReal maxAAAB;
109
110 bool isUp;
111 bool state;
112};
113//
114// HeightFieldTriangle
115//
116// HeightFieldPlane composing heightfield mesh
117//
118class HeightFieldPlane
119{
120public:
121 HeightFieldPlane():
122 trianglelist(0),
123 trianglelistReservedSize(0),
124 trianglelistCurrentSize(0)
125 {
126
127 };
128 ~HeightFieldPlane()
129 {
130 delete [] trianglelist;
131 };
132
133 inline void setMinMax()
134 {
135 const size_t asize = trianglelistCurrentSize;
136 if (asize > 0)
137 {
138 maxAAAB = trianglelist[0]->maxAAAB;
139 for (size_t k = 1; asize > k; k++)
140 {
141 if (trianglelist[k]->maxAAAB > maxAAAB)
142 maxAAAB = trianglelist[k]->maxAAAB;
143 }
144 }
145 };
146
147 void resetTriangleListSize(const size_t newSize)
148 {
149 if (trianglelistReservedSize < newSize)
150 {
151 delete [] trianglelist;
152 trianglelistReservedSize = newSize;
153 trianglelist = new HeightFieldTriangle *[newSize];
154 }
155 trianglelistCurrentSize = 0;
156 }
157
158 void addTriangle(HeightFieldTriangle *tri)
159 {
160 dIASSERT(trianglelistCurrentSize < trianglelistReservedSize);
161
162 trianglelist[trianglelistCurrentSize++] = tri;
163 }
164
165 HeightFieldTriangle **trianglelist;
166 size_t trianglelistReservedSize;
167 size_t trianglelistCurrentSize;
168
169 dReal maxAAAB;
170 dReal planeDef[4];
171};
172//
173// dxHeightfield
174//
175// Heightfield geom structure
176//
177struct dxHeightfield : public dxGeom
178{
179 dxHeightfieldData* m_p_data;
180
181 dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable );
182 ~dxHeightfield();
183
184 void computeAABB();
185
186 int dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ,
187 dxGeom *o2, const int numMaxContacts,
188 int flags, dContactGeom *contact, int skip );
189
190 enum
191 {
192 TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 4,
193 TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X = 4,
194 TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z = 4,
195 TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 1, // Triangles are easy to reallocate and hard to predict
196 };
197
198 static inline size_t AlignBufferSize(size_t value, size_t alignment) { dIASSERT((alignment & (alignment - 1)) == 0); return (value + (alignment - 1)) & ~(alignment - 1); }
199
200 void allocateTriangleBuffer(size_t numTri);
201 void resetTriangleBuffer();
202 void allocatePlaneBuffer(size_t numTri);
203 void resetPlaneBuffer();
204 void allocateHeightBuffer(size_t numX, size_t numZ);
205 void resetHeightBuffer();
206
207 void sortPlanes(const size_t numPlanes);
208
209 HeightFieldPlane **tempPlaneBuffer;
210 HeightFieldPlane *tempPlaneInstances;
211 size_t tempPlaneBufferSize;
212
213 HeightFieldTriangle *tempTriangleBuffer;
214 size_t tempTriangleBufferSize;
215
216 HeightFieldVertex **tempHeightBuffer;
217 HeightFieldVertex *tempHeightInstances;
218 size_t tempHeightBufferSizeX;
219 size_t tempHeightBufferSizeZ;
220
221};
222
223
224//------------------------------------------------------------------------------
225#endif //_DHEIGHTFIELD_H_
diff --git a/libraries/ode-0.9/ode/src/joint.cpp b/libraries/ode-0.9/ode/src/joint.cpp
deleted file mode 100644
index d83294b..0000000
--- a/libraries/ode-0.9/ode/src/joint.cpp
+++ /dev/null
@@ -1,4065 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25design note: the general principle for giving a joint the option of connecting
26to the static environment (i.e. the absolute frame) is to check the second
27body (joint->node[1].body), and if it is zero then behave as if its body
28transform is the identity.
29
30*/
31
32#include <ode/ode.h>
33#include <ode/odemath.h>
34#include <ode/rotation.h>
35#include <ode/matrix.h>
36#include "joint.h"
37
38//****************************************************************************
39// externs
40
41// extern "C" void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz);
42// extern "C" void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz);
43
44//****************************************************************************
45// utility
46
47// set three "ball-and-socket" rows in the constraint equation, and the
48// corresponding right hand side.
49
50static inline void setBall (dxJoint *joint, dxJoint::Info2 *info,
51 dVector3 anchor1, dVector3 anchor2)
52{
53 // anchor points in global coordinates with respect to body PORs.
54 dVector3 a1,a2;
55
56 int s = info->rowskip;
57
58 // set jacobian
59 info->J1l[0] = 1;
60 info->J1l[s+1] = 1;
61 info->J1l[2*s+2] = 1;
62 dMULTIPLY0_331 (a1,joint->node[0].body->posr.R,anchor1);
63 dCROSSMAT (info->J1a,a1,s,-,+);
64 if (joint->node[1].body) {
65 info->J2l[0] = -1;
66 info->J2l[s+1] = -1;
67 info->J2l[2*s+2] = -1;
68 dMULTIPLY0_331 (a2,joint->node[1].body->posr.R,anchor2);
69 dCROSSMAT (info->J2a,a2,s,+,-);
70 }
71
72 // set right hand side
73 dReal k = info->fps * info->erp;
74 if (joint->node[1].body) {
75 for (int j=0; j<3; j++) {
76 info->c[j] = k * (a2[j] + joint->node[1].body->posr.pos[j] -
77 a1[j] - joint->node[0].body->posr.pos[j]);
78 }
79 }
80 else {
81 for (int j=0; j<3; j++) {
82 info->c[j] = k * (anchor2[j] - a1[j] -
83 joint->node[0].body->posr.pos[j]);
84 }
85 }
86}
87
88
89// this is like setBall(), except that `axis' is a unit length vector
90// (in global coordinates) that should be used for the first jacobian
91// position row (the other two row vectors will be derived from this).
92// `erp1' is the erp value to use along the axis.
93
94static inline void setBall2 (dxJoint *joint, dxJoint::Info2 *info,
95 dVector3 anchor1, dVector3 anchor2,
96 dVector3 axis, dReal erp1)
97{
98 // anchor points in global coordinates with respect to body PORs.
99 dVector3 a1,a2;
100
101 int i,s = info->rowskip;
102
103 // get vectors normal to the axis. in setBall() axis,q1,q2 is [1 0 0],
104 // [0 1 0] and [0 0 1], which makes everything much easier.
105 dVector3 q1,q2;
106 dPlaneSpace (axis,q1,q2);
107
108 // set jacobian
109 for (i=0; i<3; i++) info->J1l[i] = axis[i];
110 for (i=0; i<3; i++) info->J1l[s+i] = q1[i];
111 for (i=0; i<3; i++) info->J1l[2*s+i] = q2[i];
112 dMULTIPLY0_331 (a1,joint->node[0].body->posr.R,anchor1);
113 dCROSS (info->J1a,=,a1,axis);
114 dCROSS (info->J1a+s,=,a1,q1);
115 dCROSS (info->J1a+2*s,=,a1,q2);
116 if (joint->node[1].body) {
117 for (i=0; i<3; i++) info->J2l[i] = -axis[i];
118 for (i=0; i<3; i++) info->J2l[s+i] = -q1[i];
119 for (i=0; i<3; i++) info->J2l[2*s+i] = -q2[i];
120 dMULTIPLY0_331 (a2,joint->node[1].body->posr.R,anchor2);
121 dCROSS (info->J2a,= -,a2,axis);
122 dCROSS (info->J2a+s,= -,a2,q1);
123 dCROSS (info->J2a+2*s,= -,a2,q2);
124 }
125
126 // set right hand side - measure error along (axis,q1,q2)
127 dReal k1 = info->fps * erp1;
128 dReal k = info->fps * info->erp;
129
130 for (i=0; i<3; i++) a1[i] += joint->node[0].body->posr.pos[i];
131 if (joint->node[1].body) {
132 for (i=0; i<3; i++) a2[i] += joint->node[1].body->posr.pos[i];
133 info->c[0] = k1 * (dDOT(axis,a2) - dDOT(axis,a1));
134 info->c[1] = k * (dDOT(q1,a2) - dDOT(q1,a1));
135 info->c[2] = k * (dDOT(q2,a2) - dDOT(q2,a1));
136 }
137 else {
138 info->c[0] = k1 * (dDOT(axis,anchor2) - dDOT(axis,a1));
139 info->c[1] = k * (dDOT(q1,anchor2) - dDOT(q1,a1));
140 info->c[2] = k * (dDOT(q2,anchor2) - dDOT(q2,a1));
141 }
142}
143
144
145// set three orientation rows in the constraint equation, and the
146// corresponding right hand side.
147
148static void setFixedOrientation(dxJoint *joint, dxJoint::Info2 *info, dQuaternion qrel, int start_row)
149{
150 int s = info->rowskip;
151 int start_index = start_row * s;
152
153 // 3 rows to make body rotations equal
154 info->J1a[start_index] = 1;
155 info->J1a[start_index + s + 1] = 1;
156 info->J1a[start_index + s*2+2] = 1;
157 if (joint->node[1].body) {
158 info->J2a[start_index] = -1;
159 info->J2a[start_index + s+1] = -1;
160 info->J2a[start_index + s*2+2] = -1;
161 }
162
163 // compute the right hand side. the first three elements will result in
164 // relative angular velocity of the two bodies - this is set to bring them
165 // back into alignment. the correcting angular velocity is
166 // |angular_velocity| = angle/time = erp*theta / stepsize
167 // = (erp*fps) * theta
168 // angular_velocity = |angular_velocity| * u
169 // = (erp*fps) * theta * u
170 // where rotation along unit length axis u by theta brings body 2's frame
171 // to qrel with respect to body 1's frame. using a small angle approximation
172 // for sin(), this gives
173 // angular_velocity = (erp*fps) * 2 * v
174 // where the quaternion of the relative rotation between the two bodies is
175 // q = [cos(theta/2) sin(theta/2)*u] = [s v]
176
177 // get qerr = relative rotation (rotation error) between two bodies
178 dQuaternion qerr,e;
179 if (joint->node[1].body) {
180 dQuaternion qq;
181 dQMultiply1 (qq,joint->node[0].body->q,joint->node[1].body->q);
182 dQMultiply2 (qerr,qq,qrel);
183 }
184 else {
185 dQMultiply3 (qerr,joint->node[0].body->q,qrel);
186 }
187 if (qerr[0] < 0) {
188 qerr[1] = -qerr[1]; // adjust sign of qerr to make theta small
189 qerr[2] = -qerr[2];
190 qerr[3] = -qerr[3];
191 }
192 dMULTIPLY0_331 (e,joint->node[0].body->posr.R,qerr+1); // @@@ bad SIMD padding!
193 dReal k = info->fps * info->erp;
194 info->c[start_row] = 2*k * e[0];
195 info->c[start_row+1] = 2*k * e[1];
196 info->c[start_row+2] = 2*k * e[2];
197}
198
199
200// compute anchor points relative to bodies
201
202static void setAnchors (dxJoint *j, dReal x, dReal y, dReal z,
203 dVector3 anchor1, dVector3 anchor2)
204{
205 if (j->node[0].body) {
206 dReal q[4];
207 q[0] = x - j->node[0].body->posr.pos[0];
208 q[1] = y - j->node[0].body->posr.pos[1];
209 q[2] = z - j->node[0].body->posr.pos[2];
210 q[3] = 0;
211 dMULTIPLY1_331 (anchor1,j->node[0].body->posr.R,q);
212 if (j->node[1].body) {
213 q[0] = x - j->node[1].body->posr.pos[0];
214 q[1] = y - j->node[1].body->posr.pos[1];
215 q[2] = z - j->node[1].body->posr.pos[2];
216 q[3] = 0;
217 dMULTIPLY1_331 (anchor2,j->node[1].body->posr.R,q);
218 }
219 else {
220 anchor2[0] = x;
221 anchor2[1] = y;
222 anchor2[2] = z;
223 }
224 }
225 anchor1[3] = 0;
226 anchor2[3] = 0;
227}
228
229
230// compute axes relative to bodies. either axis1 or axis2 can be 0.
231
232static void setAxes (dxJoint *j, dReal x, dReal y, dReal z,
233 dVector3 axis1, dVector3 axis2)
234{
235 if (j->node[0].body) {
236 dReal q[4];
237 q[0] = x;
238 q[1] = y;
239 q[2] = z;
240 q[3] = 0;
241 dNormalize3 (q);
242 if (axis1) {
243 dMULTIPLY1_331 (axis1,j->node[0].body->posr.R,q);
244 axis1[3] = 0;
245 }
246 if (axis2) {
247 if (j->node[1].body) {
248 dMULTIPLY1_331 (axis2,j->node[1].body->posr.R,q);
249 }
250 else {
251 axis2[0] = x;
252 axis2[1] = y;
253 axis2[2] = z;
254 }
255 axis2[3] = 0;
256 }
257 }
258}
259
260
261static void getAnchor (dxJoint *j, dVector3 result, dVector3 anchor1)
262{
263 if (j->node[0].body) {
264 dMULTIPLY0_331 (result,j->node[0].body->posr.R,anchor1);
265 result[0] += j->node[0].body->posr.pos[0];
266 result[1] += j->node[0].body->posr.pos[1];
267 result[2] += j->node[0].body->posr.pos[2];
268 }
269}
270
271
272static void getAnchor2 (dxJoint *j, dVector3 result, dVector3 anchor2)
273{
274 if (j->node[1].body) {
275 dMULTIPLY0_331 (result,j->node[1].body->posr.R,anchor2);
276 result[0] += j->node[1].body->posr.pos[0];
277 result[1] += j->node[1].body->posr.pos[1];
278 result[2] += j->node[1].body->posr.pos[2];
279 }
280 else {
281 result[0] = anchor2[0];
282 result[1] = anchor2[1];
283 result[2] = anchor2[2];
284 }
285}
286
287
288static void getAxis (dxJoint *j, dVector3 result, dVector3 axis1)
289{
290 if (j->node[0].body) {
291 dMULTIPLY0_331 (result,j->node[0].body->posr.R,axis1);
292 }
293}
294
295
296static void getAxis2 (dxJoint *j, dVector3 result, dVector3 axis2)
297{
298 if (j->node[1].body) {
299 dMULTIPLY0_331 (result,j->node[1].body->posr.R,axis2);
300 }
301 else {
302 result[0] = axis2[0];
303 result[1] = axis2[1];
304 result[2] = axis2[2];
305 }
306}
307
308
309static dReal getHingeAngleFromRelativeQuat (dQuaternion qrel, dVector3 axis)
310{
311 // the angle between the two bodies is extracted from the quaternion that
312 // represents the relative rotation between them. recall that a quaternion
313 // q is:
314 // [s,v] = [ cos(theta/2) , sin(theta/2) * u ]
315 // where s is a scalar and v is a 3-vector. u is a unit length axis and
316 // theta is a rotation along that axis. we can get theta/2 by:
317 // theta/2 = atan2 ( sin(theta/2) , cos(theta/2) )
318 // but we can't get sin(theta/2) directly, only its absolute value, i.e.:
319 // |v| = |sin(theta/2)| * |u|
320 // = |sin(theta/2)|
321 // using this value will have a strange effect. recall that there are two
322 // quaternion representations of a given rotation, q and -q. typically as
323 // a body rotates along the axis it will go through a complete cycle using
324 // one representation and then the next cycle will use the other
325 // representation. this corresponds to u pointing in the direction of the
326 // hinge axis and then in the opposite direction. the result is that theta
327 // will appear to go "backwards" every other cycle. here is a fix: if u
328 // points "away" from the direction of the hinge (motor) axis (i.e. more
329 // than 90 degrees) then use -q instead of q. this represents the same
330 // rotation, but results in the cos(theta/2) value being sign inverted.
331
332 // extract the angle from the quaternion. cost2 = cos(theta/2),
333 // sint2 = |sin(theta/2)|
334 dReal cost2 = qrel[0];
335 dReal sint2 = dSqrt (qrel[1]*qrel[1]+qrel[2]*qrel[2]+qrel[3]*qrel[3]);
336 dReal theta = (dDOT(qrel+1,axis) >= 0) ? // @@@ padding assumptions
337 (2 * dAtan2(sint2,cost2)) : // if u points in direction of axis
338 (2 * dAtan2(sint2,-cost2)); // if u points in opposite direction
339
340 // the angle we get will be between 0..2*pi, but we want to return angles
341 // between -pi..pi
342 if (theta > M_PI) theta -= 2*M_PI;
343
344 // the angle we've just extracted has the wrong sign
345 theta = -theta;
346
347 return theta;
348}
349
350
351// given two bodies (body1,body2), the hinge axis that they are connected by
352// w.r.t. body1 (axis), and the initial relative orientation between them
353// (q_initial), return the relative rotation angle. the initial relative
354// orientation corresponds to an angle of zero. if body2 is 0 then measure the
355// angle between body1 and the static frame.
356//
357// this will not return the correct angle if the bodies rotate along any axis
358// other than the given hinge axis.
359
360static dReal getHingeAngle (dxBody *body1, dxBody *body2, dVector3 axis,
361 dQuaternion q_initial)
362{
363 // get qrel = relative rotation between the two bodies
364 dQuaternion qrel;
365 if (body2) {
366 dQuaternion qq;
367 dQMultiply1 (qq,body1->q,body2->q);
368 dQMultiply2 (qrel,qq,q_initial);
369 }
370 else {
371 // pretend body2->q is the identity
372 dQMultiply3 (qrel,body1->q,q_initial);
373 }
374
375 return getHingeAngleFromRelativeQuat (qrel,axis);
376}
377
378//****************************************************************************
379// dxJointLimitMotor
380
381void dxJointLimitMotor::init (dxWorld *world)
382{
383 vel = 0;
384 fmax = 0;
385 lostop = -dInfinity;
386 histop = dInfinity;
387 fudge_factor = 1;
388 normal_cfm = world->global_cfm;
389 stop_erp = world->global_erp;
390 stop_cfm = world->global_cfm;
391 bounce = 0;
392 limit = 0;
393 limit_err = 0;
394}
395
396
397void dxJointLimitMotor::set (int num, dReal value)
398{
399 switch (num) {
400 case dParamLoStop:
401 lostop = value;
402 break;
403 case dParamHiStop:
404 histop = value;
405 break;
406 case dParamVel:
407 vel = value;
408 break;
409 case dParamFMax:
410 if (value >= 0) fmax = value;
411 break;
412 case dParamFudgeFactor:
413 if (value >= 0 && value <= 1) fudge_factor = value;
414 break;
415 case dParamBounce:
416 bounce = value;
417 break;
418 case dParamCFM:
419 normal_cfm = value;
420 break;
421 case dParamStopERP:
422 stop_erp = value;
423 break;
424 case dParamStopCFM:
425 stop_cfm = value;
426 break;
427 }
428}
429
430
431dReal dxJointLimitMotor::get (int num)
432{
433 switch (num) {
434 case dParamLoStop: return lostop;
435 case dParamHiStop: return histop;
436 case dParamVel: return vel;
437 case dParamFMax: return fmax;
438 case dParamFudgeFactor: return fudge_factor;
439 case dParamBounce: return bounce;
440 case dParamCFM: return normal_cfm;
441 case dParamStopERP: return stop_erp;
442 case dParamStopCFM: return stop_cfm;
443 default: return 0;
444 }
445}
446
447
448int dxJointLimitMotor::testRotationalLimit (dReal angle)
449{
450 if (angle <= lostop) {
451 limit = 1;
452 limit_err = angle - lostop;
453 return 1;
454 }
455 else if (angle >= histop) {
456 limit = 2;
457 limit_err = angle - histop;
458 return 1;
459 }
460 else {
461 limit = 0;
462 return 0;
463 }
464}
465
466
467int dxJointLimitMotor::addLimot (dxJoint *joint,
468 dxJoint::Info2 *info, int row,
469 dVector3 ax1, int rotational)
470{
471 int srow = row * info->rowskip;
472
473 // if the joint is powered, or has joint limits, add in the extra row
474 int powered = fmax > 0;
475 if (powered || limit) {
476 dReal *J1 = rotational ? info->J1a : info->J1l;
477 dReal *J2 = rotational ? info->J2a : info->J2l;
478
479 J1[srow+0] = ax1[0];
480 J1[srow+1] = ax1[1];
481 J1[srow+2] = ax1[2];
482 if (joint->node[1].body) {
483 J2[srow+0] = -ax1[0];
484 J2[srow+1] = -ax1[1];
485 J2[srow+2] = -ax1[2];
486 }
487
488 // linear limot torque decoupling step:
489 //
490 // if this is a linear limot (e.g. from a slider), we have to be careful
491 // that the linear constraint forces (+/- ax1) applied to the two bodies
492 // do not create a torque couple. in other words, the points that the
493 // constraint force is applied at must lie along the same ax1 axis.
494 // a torque couple will result in powered or limited slider-jointed free
495 // bodies from gaining angular momentum.
496 // the solution used here is to apply the constraint forces at the point
497 // halfway between the body centers. there is no penalty (other than an
498 // extra tiny bit of computation) in doing this adjustment. note that we
499 // only need to do this if the constraint connects two bodies.
500
501 dVector3 ltd; // Linear Torque Decoupling vector (a torque)
502 if (!rotational && joint->node[1].body) {
503 dVector3 c;
504 c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
505 c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
506 c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
507 dCROSS (ltd,=,c,ax1);
508 info->J1a[srow+0] = ltd[0];
509 info->J1a[srow+1] = ltd[1];
510 info->J1a[srow+2] = ltd[2];
511 info->J2a[srow+0] = ltd[0];
512 info->J2a[srow+1] = ltd[1];
513 info->J2a[srow+2] = ltd[2];
514 }
515
516 // if we're limited low and high simultaneously, the joint motor is
517 // ineffective
518 if (limit && (lostop == histop)) powered = 0;
519
520 if (powered) {
521 info->cfm[row] = normal_cfm;
522 if (! limit) {
523 info->c[row] = vel;
524 info->lo[row] = -fmax;
525 info->hi[row] = fmax;
526 }
527 else {
528 // the joint is at a limit, AND is being powered. if the joint is
529 // being powered into the limit then we apply the maximum motor force
530 // in that direction, because the motor is working against the
531 // immovable limit. if the joint is being powered away from the limit
532 // then we have problems because actually we need *two* lcp
533 // constraints to handle this case. so we fake it and apply some
534 // fraction of the maximum force. the fraction to use can be set as
535 // a fudge factor.
536
537 dReal fm = fmax;
538 if ((vel > 0) || (vel==0 && limit==2)) fm = -fm;
539
540 // if we're powering away from the limit, apply the fudge factor
541 if ((limit==1 && vel > 0) || (limit==2 && vel < 0)) fm *= fudge_factor;
542
543 if (rotational) {
544 dBodyAddTorque (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],
545 -fm*ax1[2]);
546 if (joint->node[1].body)
547 dBodyAddTorque (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
548 }
549 else {
550 dBodyAddForce (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],-fm*ax1[2]);
551 if (joint->node[1].body) {
552 dBodyAddForce (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
553
554 // linear limot torque decoupling step: refer to above discussion
555 dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1],
556 -fm*ltd[2]);
557 dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1],
558 -fm*ltd[2]);
559 }
560 }
561 }
562 }
563
564 if (limit) {
565 dReal k = info->fps * stop_erp;
566 info->c[row] = -k * limit_err;
567 info->cfm[row] = stop_cfm;
568
569 if (lostop == histop) {
570 // limited low and high simultaneously
571 info->lo[row] = -dInfinity;
572 info->hi[row] = dInfinity;
573 }
574 else {
575 if (limit == 1) {
576 // low limit
577 info->lo[row] = 0;
578 info->hi[row] = dInfinity;
579 }
580 else {
581 // high limit
582 info->lo[row] = -dInfinity;
583 info->hi[row] = 0;
584 }
585
586 // deal with bounce
587 if (bounce > 0) {
588 // calculate joint velocity
589 dReal vel;
590 if (rotational) {
591 vel = dDOT(joint->node[0].body->avel,ax1);
592 if (joint->node[1].body)
593 vel -= dDOT(joint->node[1].body->avel,ax1);
594 }
595 else {
596 vel = dDOT(joint->node[0].body->lvel,ax1);
597 if (joint->node[1].body)
598 vel -= dDOT(joint->node[1].body->lvel,ax1);
599 }
600
601 // only apply bounce if the velocity is incoming, and if the
602 // resulting c[] exceeds what we already have.
603 if (limit == 1) {
604 // low limit
605 if (vel < 0) {
606 dReal newc = -bounce * vel;
607 if (newc > info->c[row]) info->c[row] = newc;
608 }
609 }
610 else {
611 // high limit - all those computations are reversed
612 if (vel > 0) {
613 dReal newc = -bounce * vel;
614 if (newc < info->c[row]) info->c[row] = newc;
615 }
616 }
617 }
618 }
619 }
620 return 1;
621 }
622 else return 0;
623}
624
625//****************************************************************************
626// ball and socket
627
628static void ballInit (dxJointBall *j)
629{
630 dSetZero (j->anchor1,4);
631 dSetZero (j->anchor2,4);
632 j->erp = j->world->global_erp;
633 j->cfm = j->world->global_cfm;
634}
635
636
637static void ballGetInfo1 (dxJointBall *j, dxJoint::Info1 *info)
638{
639 info->m = 3;
640 info->nub = 3;
641}
642
643
644static void ballGetInfo2 (dxJointBall *joint, dxJoint::Info2 *info)
645{
646 info->erp = joint->erp;
647 info->cfm[0] = joint->cfm;
648 info->cfm[1] = joint->cfm;
649 info->cfm[2] = joint->cfm;
650 setBall (joint,info,joint->anchor1,joint->anchor2);
651}
652
653
654void dJointSetBallAnchor (dJointID j, dReal x, dReal y, dReal z)
655{
656 dxJointBall* joint = (dxJointBall*)j;
657 dUASSERT(joint,"bad joint argument");
658 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
659 setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
660}
661
662
663void dJointSetBallAnchor2 (dJointID j, dReal x, dReal y, dReal z)
664{
665 dxJointBall* joint = (dxJointBall*)j;
666 dUASSERT(joint,"bad joint argument");
667 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
668 joint->anchor2[0] = x;
669 joint->anchor2[1] = y;
670 joint->anchor2[2] = z;
671 joint->anchor2[3] = 0;
672
673}
674
675void dJointGetBallAnchor (dJointID j, dVector3 result)
676{
677 dxJointBall* joint = (dxJointBall*)j;
678 dUASSERT(joint,"bad joint argument");
679 dUASSERT(result,"bad result argument");
680 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
681 if (joint->flags & dJOINT_REVERSE)
682 getAnchor2 (joint,result,joint->anchor2);
683 else
684 getAnchor (joint,result,joint->anchor1);
685}
686
687
688void dJointGetBallAnchor2 (dJointID j, dVector3 result)
689{
690 dxJointBall* joint = (dxJointBall*)j;
691 dUASSERT(joint,"bad joint argument");
692 dUASSERT(result,"bad result argument");
693 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
694 if (joint->flags & dJOINT_REVERSE)
695 getAnchor (joint,result,joint->anchor1);
696 else
697 getAnchor2 (joint,result,joint->anchor2);
698}
699
700
701void dxJointBall::set (int num, dReal value)
702{
703 switch (num) {
704 case dParamCFM:
705 cfm = value;
706 break;
707 case dParamERP:
708 erp = value;
709 break;
710 }
711}
712
713
714dReal dxJointBall::get (int num)
715{
716 switch (num) {
717 case dParamCFM:
718 return cfm;
719 case dParamERP:
720 return erp;
721 default:
722 return 0;
723 }
724}
725
726
727void dJointSetBallParam (dJointID j, int parameter, dReal value)
728{
729 dxJointBall* joint = (dxJointBall*)j;
730 dUASSERT(joint,"bad joint argument");
731 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball joint");
732 joint->set (parameter,value);
733}
734
735
736dReal dJointGetBallParam (dJointID j, int parameter)
737{
738 dxJointBall* joint = (dxJointBall*)j;
739 dUASSERT(joint,"bad joint argument");
740 dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball joint");
741 return joint->get (parameter);
742}
743
744
745dxJoint::Vtable __dball_vtable = {
746 sizeof(dxJointBall),
747 (dxJoint::init_fn*) ballInit,
748 (dxJoint::getInfo1_fn*) ballGetInfo1,
749 (dxJoint::getInfo2_fn*) ballGetInfo2,
750 dJointTypeBall};
751
752//****************************************************************************
753// hinge
754
755static void hingeInit (dxJointHinge *j)
756{
757 dSetZero (j->anchor1,4);
758 dSetZero (j->anchor2,4);
759 dSetZero (j->axis1,4);
760 j->axis1[0] = 1;
761 dSetZero (j->axis2,4);
762 j->axis2[0] = 1;
763 dSetZero (j->qrel,4);
764 j->limot.init (j->world);
765}
766
767
768static void hingeGetInfo1 (dxJointHinge *j, dxJoint::Info1 *info)
769{
770 info->nub = 5;
771
772 // see if joint is powered
773 if (j->limot.fmax > 0)
774 info->m = 6; // powered hinge needs an extra constraint row
775 else info->m = 5;
776
777 // see if we're at a joint limit.
778 if ((j->limot.lostop >= -M_PI || j->limot.histop <= M_PI) &&
779 j->limot.lostop <= j->limot.histop) {
780 dReal angle = getHingeAngle (j->node[0].body,j->node[1].body,j->axis1,
781 j->qrel);
782 if (j->limot.testRotationalLimit (angle)) info->m = 6;
783 }
784}
785
786
787static void hingeGetInfo2 (dxJointHinge *joint, dxJoint::Info2 *info)
788{
789 // set the three ball-and-socket rows
790 setBall (joint,info,joint->anchor1,joint->anchor2);
791
792 // set the two hinge rows. the hinge axis should be the only unconstrained
793 // rotational axis, the angular velocity of the two bodies perpendicular to
794 // the hinge axis should be equal. thus the constraint equations are
795 // p*w1 - p*w2 = 0
796 // q*w1 - q*w2 = 0
797 // where p and q are unit vectors normal to the hinge axis, and w1 and w2
798 // are the angular velocity vectors of the two bodies.
799
800 dVector3 ax1; // length 1 joint axis in global coordinates, from 1st body
801 dVector3 p,q; // plane space vectors for ax1
802 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
803 dPlaneSpace (ax1,p,q);
804
805 int s3=3*info->rowskip;
806 int s4=4*info->rowskip;
807
808 info->J1a[s3+0] = p[0];
809 info->J1a[s3+1] = p[1];
810 info->J1a[s3+2] = p[2];
811 info->J1a[s4+0] = q[0];
812 info->J1a[s4+1] = q[1];
813 info->J1a[s4+2] = q[2];
814
815 if (joint->node[1].body) {
816 info->J2a[s3+0] = -p[0];
817 info->J2a[s3+1] = -p[1];
818 info->J2a[s3+2] = -p[2];
819 info->J2a[s4+0] = -q[0];
820 info->J2a[s4+1] = -q[1];
821 info->J2a[s4+2] = -q[2];
822 }
823
824 // compute the right hand side of the constraint equation. set relative
825 // body velocities along p and q to bring the hinge back into alignment.
826 // if ax1,ax2 are the unit length hinge axes as computed from body1 and
827 // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
828 // if `theta' is the angle between ax1 and ax2, we need an angular velocity
829 // along u to cover angle erp*theta in one step :
830 // |angular_velocity| = angle/time = erp*theta / stepsize
831 // = (erp*fps) * theta
832 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
833 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
834 // ...as ax1 and ax2 are unit length. if theta is smallish,
835 // theta ~= sin(theta), so
836 // angular_velocity = (erp*fps) * (ax1 x ax2)
837 // ax1 x ax2 is in the plane space of ax1, so we project the angular
838 // velocity to p and q to find the right hand side.
839
840 dVector3 ax2,b;
841 if (joint->node[1].body) {
842 dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
843 }
844 else {
845 ax2[0] = joint->axis2[0];
846 ax2[1] = joint->axis2[1];
847 ax2[2] = joint->axis2[2];
848 }
849 dCROSS (b,=,ax1,ax2);
850 dReal k = info->fps * info->erp;
851 info->c[3] = k * dDOT(b,p);
852 info->c[4] = k * dDOT(b,q);
853
854 // if the hinge is powered, or has joint limits, add in the stuff
855 joint->limot.addLimot (joint,info,5,ax1,1);
856}
857
858
859// compute initial relative rotation body1 -> body2, or env -> body1
860
861static void hingeComputeInitialRelativeRotation (dxJointHinge *joint)
862{
863 if (joint->node[0].body) {
864 if (joint->node[1].body) {
865 dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
866 }
867 else {
868 // set joint->qrel to the transpose of the first body q
869 joint->qrel[0] = joint->node[0].body->q[0];
870 for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
871 }
872 }
873}
874
875
876void dJointSetHingeAnchor (dJointID j, dReal x, dReal y, dReal z)
877{
878 dxJointHinge* joint = (dxJointHinge*)j;
879 dUASSERT(joint,"bad joint argument");
880 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
881 setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
882 hingeComputeInitialRelativeRotation (joint);
883}
884
885
886void dJointSetHingeAnchorDelta (dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz)
887{
888 dxJointHinge* joint = (dxJointHinge*)j;
889 dUASSERT(joint,"bad joint argument");
890 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
891
892 if (joint->node[0].body) {
893 dReal q[4];
894 q[0] = x - joint->node[0].body->posr.pos[0];
895 q[1] = y - joint->node[0].body->posr.pos[1];
896 q[2] = z - joint->node[0].body->posr.pos[2];
897 q[3] = 0;
898 dMULTIPLY1_331 (joint->anchor1,joint->node[0].body->posr.R,q);
899
900 if (joint->node[1].body) {
901 q[0] = x - joint->node[1].body->posr.pos[0];
902 q[1] = y - joint->node[1].body->posr.pos[1];
903 q[2] = z - joint->node[1].body->posr.pos[2];
904 q[3] = 0;
905 dMULTIPLY1_331 (joint->anchor2,joint->node[1].body->posr.R,q);
906 }
907 else {
908 // Move the relative displacement between the passive body and the
909 // anchor in the same direction as the passive body has just moved
910 joint->anchor2[0] = x + dx;
911 joint->anchor2[1] = y + dy;
912 joint->anchor2[2] = z + dz;
913 }
914 }
915 joint->anchor1[3] = 0;
916 joint->anchor2[3] = 0;
917
918 hingeComputeInitialRelativeRotation (joint);
919}
920
921
922
923void dJointSetHingeAxis (dJointID j, dReal x, dReal y, dReal z)
924{
925 dxJointHinge* joint = (dxJointHinge*)j;
926 dUASSERT(joint,"bad joint argument");
927 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
928 setAxes (joint,x,y,z,joint->axis1,joint->axis2);
929 hingeComputeInitialRelativeRotation (joint);
930}
931
932
933void dJointGetHingeAnchor (dJointID j, dVector3 result)
934{
935 dxJointHinge* joint = (dxJointHinge*)j;
936 dUASSERT(joint,"bad joint argument");
937 dUASSERT(result,"bad result argument");
938 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
939 if (joint->flags & dJOINT_REVERSE)
940 getAnchor2 (joint,result,joint->anchor2);
941 else
942 getAnchor (joint,result,joint->anchor1);
943}
944
945
946void dJointGetHingeAnchor2 (dJointID j, dVector3 result)
947{
948 dxJointHinge* joint = (dxJointHinge*)j;
949 dUASSERT(joint,"bad joint argument");
950 dUASSERT(result,"bad result argument");
951 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
952 if (joint->flags & dJOINT_REVERSE)
953 getAnchor (joint,result,joint->anchor1);
954 else
955 getAnchor2 (joint,result,joint->anchor2);
956}
957
958
959void dJointGetHingeAxis (dJointID j, dVector3 result)
960{
961 dxJointHinge* joint = (dxJointHinge*)j;
962 dUASSERT(joint,"bad joint argument");
963 dUASSERT(result,"bad result argument");
964 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
965 getAxis (joint,result,joint->axis1);
966}
967
968
969void dJointSetHingeParam (dJointID j, int parameter, dReal value)
970{
971 dxJointHinge* joint = (dxJointHinge*)j;
972 dUASSERT(joint,"bad joint argument");
973 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
974 joint->limot.set (parameter,value);
975}
976
977
978dReal dJointGetHingeParam (dJointID j, int parameter)
979{
980 dxJointHinge* joint = (dxJointHinge*)j;
981 dUASSERT(joint,"bad joint argument");
982 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
983 return joint->limot.get (parameter);
984}
985
986
987dReal dJointGetHingeAngle (dJointID j)
988{
989 dxJointHinge* joint = (dxJointHinge*)j;
990 dAASSERT(joint);
991 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
992 if (joint->node[0].body) {
993 dReal ang = getHingeAngle (joint->node[0].body,joint->node[1].body,joint->axis1,
994 joint->qrel);
995 if (joint->flags & dJOINT_REVERSE)
996 return -ang;
997 else
998 return ang;
999 }
1000 else return 0;
1001}
1002
1003
1004dReal dJointGetHingeAngleRate (dJointID j)
1005{
1006 dxJointHinge* joint = (dxJointHinge*)j;
1007 dAASSERT(joint);
1008 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
1009 if (joint->node[0].body) {
1010 dVector3 axis;
1011 dMULTIPLY0_331 (axis,joint->node[0].body->posr.R,joint->axis1);
1012 dReal rate = dDOT(axis,joint->node[0].body->avel);
1013 if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
1014 if (joint->flags & dJOINT_REVERSE) rate = - rate;
1015 return rate;
1016 }
1017 else return 0;
1018}
1019
1020
1021void dJointAddHingeTorque (dJointID j, dReal torque)
1022{
1023 dxJointHinge* joint = (dxJointHinge*)j;
1024 dVector3 axis;
1025 dAASSERT(joint);
1026 dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
1027
1028 if (joint->flags & dJOINT_REVERSE)
1029 torque = -torque;
1030
1031 getAxis (joint,axis,joint->axis1);
1032 axis[0] *= torque;
1033 axis[1] *= torque;
1034 axis[2] *= torque;
1035
1036 if (joint->node[0].body != 0)
1037 dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
1038 if (joint->node[1].body != 0)
1039 dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
1040}
1041
1042
1043dxJoint::Vtable __dhinge_vtable = {
1044 sizeof(dxJointHinge),
1045 (dxJoint::init_fn*) hingeInit,
1046 (dxJoint::getInfo1_fn*) hingeGetInfo1,
1047 (dxJoint::getInfo2_fn*) hingeGetInfo2,
1048 dJointTypeHinge};
1049
1050//****************************************************************************
1051// slider
1052
1053static void sliderInit (dxJointSlider *j)
1054{
1055 dSetZero (j->axis1,4);
1056 j->axis1[0] = 1;
1057 dSetZero (j->qrel,4);
1058 dSetZero (j->offset,4);
1059 j->limot.init (j->world);
1060}
1061
1062
1063dReal dJointGetSliderPosition (dJointID j)
1064{
1065 dxJointSlider* joint = (dxJointSlider*)j;
1066 dUASSERT(joint,"bad joint argument");
1067 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1068
1069 // get axis1 in global coordinates
1070 dVector3 ax1,q;
1071 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
1072
1073 if (joint->node[1].body) {
1074 // get body2 + offset point in global coordinates
1075 dMULTIPLY0_331 (q,joint->node[1].body->posr.R,joint->offset);
1076 for (int i=0; i<3; i++) q[i] = joint->node[0].body->posr.pos[i] - q[i] -
1077 joint->node[1].body->posr.pos[i];
1078 }
1079 else {
1080 for (int i=0; i<3; i++) q[i] = joint->node[0].body->posr.pos[i] -
1081 joint->offset[i];
1082
1083 }
1084 return dDOT(ax1,q);
1085}
1086
1087
1088dReal dJointGetSliderPositionRate (dJointID j)
1089{
1090 dxJointSlider* joint = (dxJointSlider*)j;
1091 dUASSERT(joint,"bad joint argument");
1092 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1093
1094 // get axis1 in global coordinates
1095 dVector3 ax1;
1096 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
1097
1098 if (joint->node[1].body) {
1099 return dDOT(ax1,joint->node[0].body->lvel) -
1100 dDOT(ax1,joint->node[1].body->lvel);
1101 }
1102 else {
1103 return dDOT(ax1,joint->node[0].body->lvel);
1104 }
1105}
1106
1107
1108static void sliderGetInfo1 (dxJointSlider *j, dxJoint::Info1 *info)
1109{
1110 info->nub = 5;
1111
1112 // see if joint is powered
1113 if (j->limot.fmax > 0)
1114 info->m = 6; // powered slider needs an extra constraint row
1115 else info->m = 5;
1116
1117 // see if we're at a joint limit.
1118 j->limot.limit = 0;
1119 if ((j->limot.lostop > -dInfinity || j->limot.histop < dInfinity) &&
1120 j->limot.lostop <= j->limot.histop) {
1121 // measure joint position
1122 dReal pos = dJointGetSliderPosition (j);
1123 if (pos <= j->limot.lostop) {
1124 j->limot.limit = 1;
1125 j->limot.limit_err = pos - j->limot.lostop;
1126 info->m = 6;
1127 }
1128 else if (pos >= j->limot.histop) {
1129 j->limot.limit = 2;
1130 j->limot.limit_err = pos - j->limot.histop;
1131 info->m = 6;
1132 }
1133 }
1134}
1135
1136
1137static void sliderGetInfo2 (dxJointSlider *joint, dxJoint::Info2 *info)
1138{
1139 int i,s = info->rowskip;
1140 int s3=3*s,s4=4*s;
1141
1142 // pull out pos and R for both bodies. also get the `connection'
1143 // vector pos2-pos1.
1144
1145 dReal *pos1,*pos2,*R1,*R2;
1146 dVector3 c;
1147 pos1 = joint->node[0].body->posr.pos;
1148 R1 = joint->node[0].body->posr.R;
1149 if (joint->node[1].body) {
1150 pos2 = joint->node[1].body->posr.pos;
1151 R2 = joint->node[1].body->posr.R;
1152 for (i=0; i<3; i++) c[i] = pos2[i] - pos1[i];
1153 }
1154 else {
1155 pos2 = 0;
1156 R2 = 0;
1157 }
1158
1159 // 3 rows to make body rotations equal
1160 setFixedOrientation(joint, info, joint->qrel, 0);
1161
1162 // remaining two rows. we want: vel2 = vel1 + w1 x c ... but this would
1163 // result in three equations, so we project along the planespace vectors
1164 // so that sliding along the slider axis is disregarded. for symmetry we
1165 // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2.
1166
1167 dVector3 ax1; // joint axis in global coordinates (unit length)
1168 dVector3 p,q; // plane space of ax1
1169 dMULTIPLY0_331 (ax1,R1,joint->axis1);
1170 dPlaneSpace (ax1,p,q);
1171 if (joint->node[1].body) {
1172 dVector3 tmp;
1173 dCROSS (tmp, = REAL(0.5) * ,c,p);
1174 for (i=0; i<3; i++) info->J1a[s3+i] = tmp[i];
1175 for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i];
1176 dCROSS (tmp, = REAL(0.5) * ,c,q);
1177 for (i=0; i<3; i++) info->J1a[s4+i] = tmp[i];
1178 for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i];
1179 for (i=0; i<3; i++) info->J2l[s3+i] = -p[i];
1180 for (i=0; i<3; i++) info->J2l[s4+i] = -q[i];
1181 }
1182 for (i=0; i<3; i++) info->J1l[s3+i] = p[i];
1183 for (i=0; i<3; i++) info->J1l[s4+i] = q[i];
1184
1185 // compute last two elements of right hand side. we want to align the offset
1186 // point (in body 2's frame) with the center of body 1.
1187 dReal k = info->fps * info->erp;
1188 if (joint->node[1].body) {
1189 dVector3 ofs; // offset point in global coordinates
1190 dMULTIPLY0_331 (ofs,R2,joint->offset);
1191 for (i=0; i<3; i++) c[i] += ofs[i];
1192 info->c[3] = k * dDOT(p,c);
1193 info->c[4] = k * dDOT(q,c);
1194 }
1195 else {
1196 dVector3 ofs; // offset point in global coordinates
1197 for (i=0; i<3; i++) ofs[i] = joint->offset[i] - pos1[i];
1198 info->c[3] = k * dDOT(p,ofs);
1199 info->c[4] = k * dDOT(q,ofs);
1200 }
1201
1202 // if the slider is powered, or has joint limits, add in the extra row
1203 joint->limot.addLimot (joint,info,5,ax1,0);
1204}
1205
1206
1207void dJointSetSliderAxis (dJointID j, dReal x, dReal y, dReal z)
1208{
1209 dxJointSlider* joint = (dxJointSlider*)j;
1210 int i;
1211 dUASSERT(joint,"bad joint argument");
1212 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1213 setAxes (joint,x,y,z,joint->axis1,0);
1214
1215 // compute initial relative rotation body1 -> body2, or env -> body1
1216 // also compute center of body1 w.r.t body 2
1217 if (joint->node[1].body) {
1218 dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
1219 dVector3 c;
1220 for (i=0; i<3; i++)
1221 c[i] = joint->node[0].body->posr.pos[i] - joint->node[1].body->posr.pos[i];
1222 dMULTIPLY1_331 (joint->offset,joint->node[1].body->posr.R,c);
1223 }
1224 else {
1225 // set joint->qrel to the transpose of the first body's q
1226 joint->qrel[0] = joint->node[0].body->q[0];
1227 for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
1228 for (i=0; i<3; i++) joint->offset[i] = joint->node[0].body->posr.pos[i];
1229 }
1230}
1231
1232
1233void dJointSetSliderAxisDelta (dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz)
1234{
1235 dxJointSlider* joint = (dxJointSlider*)j;
1236 int i;
1237 dUASSERT(joint,"bad joint argument");
1238 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1239 setAxes (joint,x,y,z,joint->axis1,0);
1240
1241 // compute initial relative rotation body1 -> body2, or env -> body1
1242 // also compute center of body1 w.r.t body 2
1243 if (joint->node[1].body) {
1244 dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
1245 dVector3 c;
1246 for (i=0; i<3; i++)
1247 c[i] = joint->node[0].body->posr.pos[i] - joint->node[1].body->posr.pos[i];
1248 dMULTIPLY1_331 (joint->offset,joint->node[1].body->posr.R,c);
1249 }
1250 else {
1251 // set joint->qrel to the transpose of the first body's q
1252 joint->qrel[0] = joint->node[0].body->q[0];
1253
1254 for (i=1; i<4; i++)
1255 joint->qrel[i] = -joint->node[0].body->q[i];
1256
1257 joint->offset[0] = joint->node[0].body->posr.pos[0] + dx;
1258 joint->offset[1] = joint->node[0].body->posr.pos[1] + dy;
1259 joint->offset[2] = joint->node[0].body->posr.pos[2] + dz;
1260 }
1261}
1262
1263
1264
1265void dJointGetSliderAxis (dJointID j, dVector3 result)
1266{
1267 dxJointSlider* joint = (dxJointSlider*)j;
1268 dUASSERT(joint,"bad joint argument");
1269 dUASSERT(result,"bad result argument");
1270 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1271 getAxis (joint,result,joint->axis1);
1272}
1273
1274
1275void dJointSetSliderParam (dJointID j, int parameter, dReal value)
1276{
1277 dxJointSlider* joint = (dxJointSlider*)j;
1278 dUASSERT(joint,"bad joint argument");
1279 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1280 joint->limot.set (parameter,value);
1281}
1282
1283
1284dReal dJointGetSliderParam (dJointID j, int parameter)
1285{
1286 dxJointSlider* joint = (dxJointSlider*)j;
1287 dUASSERT(joint,"bad joint argument");
1288 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1289 return joint->limot.get (parameter);
1290}
1291
1292
1293void dJointAddSliderForce (dJointID j, dReal force)
1294{
1295 dxJointSlider* joint = (dxJointSlider*)j;
1296 dVector3 axis;
1297 dUASSERT(joint,"bad joint argument");
1298 dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
1299
1300 if (joint->flags & dJOINT_REVERSE)
1301 force -= force;
1302
1303 getAxis (joint,axis,joint->axis1);
1304 axis[0] *= force;
1305 axis[1] *= force;
1306 axis[2] *= force;
1307
1308 if (joint->node[0].body != 0)
1309 dBodyAddForce (joint->node[0].body,axis[0],axis[1],axis[2]);
1310 if (joint->node[1].body != 0)
1311 dBodyAddForce(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
1312
1313 if (joint->node[0].body != 0 && joint->node[1].body != 0) {
1314 // linear torque decoupling:
1315 // we have to compensate the torque, that this slider force may generate
1316 // if body centers are not aligned along the slider axis
1317
1318 dVector3 ltd; // Linear Torque Decoupling vector (a torque)
1319
1320 dVector3 c;
1321 c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
1322 c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
1323 c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
1324 dCROSS (ltd,=,c,axis);
1325
1326 dBodyAddTorque (joint->node[0].body,ltd[0],ltd[1], ltd[2]);
1327 dBodyAddTorque (joint->node[1].body,ltd[0],ltd[1], ltd[2]);
1328 }
1329}
1330
1331
1332dxJoint::Vtable __dslider_vtable = {
1333 sizeof(dxJointSlider),
1334 (dxJoint::init_fn*) sliderInit,
1335 (dxJoint::getInfo1_fn*) sliderGetInfo1,
1336 (dxJoint::getInfo2_fn*) sliderGetInfo2,
1337 dJointTypeSlider};
1338
1339//****************************************************************************
1340// contact
1341
1342static void contactInit (dxJointContact *j)
1343{
1344 // default frictionless contact. hmmm, this info gets overwritten straight
1345 // away anyway, so why bother?
1346#if 0 /* so don't bother ;) */
1347 j->contact.surface.mode = 0;
1348 j->contact.surface.mu = 0;
1349 dSetZero (j->contact.geom.pos,4);
1350 dSetZero (j->contact.geom.normal,4);
1351 j->contact.geom.depth = 0;
1352#endif
1353}
1354
1355
1356static void contactGetInfo1 (dxJointContact *j, dxJoint::Info1 *info)
1357{
1358 // make sure mu's >= 0, then calculate number of constraint rows and number
1359 // of unbounded rows.
1360 int m = 1, nub=0;
1361 if (j->contact.surface.mu < 0) j->contact.surface.mu = 0;
1362 if (j->contact.surface.mode & dContactMu2) {
1363 if (j->contact.surface.mu > 0) m++;
1364 if (j->contact.surface.mu2 < 0) j->contact.surface.mu2 = 0;
1365 if (j->contact.surface.mu2 > 0) m++;
1366 if (j->contact.surface.mu == dInfinity) nub ++;
1367 if (j->contact.surface.mu2 == dInfinity) nub ++;
1368 }
1369 else {
1370 if (j->contact.surface.mu > 0) m += 2;
1371 if (j->contact.surface.mu == dInfinity) nub += 2;
1372 }
1373
1374 j->the_m = m;
1375 info->m = m;
1376 info->nub = nub;
1377}
1378
1379
1380static void contactGetInfo2 (dxJointContact *j, dxJoint::Info2 *info)
1381{
1382 int s = info->rowskip;
1383 int s2 = 2*s;
1384
1385 // get normal, with sign adjusted for body1/body2 polarity
1386 dVector3 normal;
1387 if (j->flags & dJOINT_REVERSE) {
1388 normal[0] = - j->contact.geom.normal[0];
1389 normal[1] = - j->contact.geom.normal[1];
1390 normal[2] = - j->contact.geom.normal[2];
1391 }
1392 else {
1393 normal[0] = j->contact.geom.normal[0];
1394 normal[1] = j->contact.geom.normal[1];
1395 normal[2] = j->contact.geom.normal[2];
1396 }
1397 normal[3] = 0; // @@@ hmmm
1398
1399 // c1,c2 = contact points with respect to body PORs
1400 dVector3 c1,c2;
1401 c1[0] = j->contact.geom.pos[0] - j->node[0].body->posr.pos[0];
1402 c1[1] = j->contact.geom.pos[1] - j->node[0].body->posr.pos[1];
1403 c1[2] = j->contact.geom.pos[2] - j->node[0].body->posr.pos[2];
1404
1405 // set jacobian for normal
1406 info->J1l[0] = normal[0];
1407 info->J1l[1] = normal[1];
1408 info->J1l[2] = normal[2];
1409 dCROSS (info->J1a,=,c1,normal);
1410 if (j->node[1].body) {
1411 c2[0] = j->contact.geom.pos[0] - j->node[1].body->posr.pos[0];
1412 c2[1] = j->contact.geom.pos[1] - j->node[1].body->posr.pos[1];
1413 c2[2] = j->contact.geom.pos[2] - j->node[1].body->posr.pos[2];
1414 info->J2l[0] = -normal[0];
1415 info->J2l[1] = -normal[1];
1416 info->J2l[2] = -normal[2];
1417 dCROSS (info->J2a,= -,c2,normal);
1418 }
1419
1420 // set right hand side and cfm value for normal
1421 dReal erp = info->erp;
1422 if (j->contact.surface.mode & dContactSoftERP)
1423 erp = j->contact.surface.soft_erp;
1424 dReal k = info->fps * erp;
1425 dReal depth = j->contact.geom.depth - j->world->contactp.min_depth;
1426 if (depth < 0) depth = 0;
1427
1428 const dReal maxvel = j->world->contactp.max_vel;
1429 info->c[0] = k*depth;
1430 if (info->c[0] > maxvel)
1431 info->c[0] = maxvel;
1432
1433 if (j->contact.surface.mode & dContactSoftCFM)
1434 info->cfm[0] = j->contact.surface.soft_cfm;
1435
1436 // deal with bounce
1437 if (j->contact.surface.mode & dContactBounce) {
1438 // calculate outgoing velocity (-ve for incoming contact)
1439 dReal outgoing = dDOT(info->J1l,j->node[0].body->lvel) +
1440 dDOT(info->J1a,j->node[0].body->avel);
1441 if (j->node[1].body) {
1442 outgoing += dDOT(info->J2l,j->node[1].body->lvel) +
1443 dDOT(info->J2a,j->node[1].body->avel);
1444 }
1445 // only apply bounce if the outgoing velocity is greater than the
1446 // threshold, and if the resulting c[0] exceeds what we already have.
1447 if (j->contact.surface.bounce_vel >= 0 &&
1448 (-outgoing) > j->contact.surface.bounce_vel) {
1449 dReal newc = - j->contact.surface.bounce * outgoing;
1450 if (newc > info->c[0]) info->c[0] = newc;
1451 }
1452 }
1453
1454 // set LCP limits for normal
1455 info->lo[0] = 0;
1456 info->hi[0] = dInfinity;
1457
1458 // now do jacobian for tangential forces
1459 dVector3 t1,t2; // two vectors tangential to normal
1460
1461 // first friction direction
1462 if (j->the_m >= 2) {
1463 if (j->contact.surface.mode & dContactFDir1) { // use fdir1 ?
1464 t1[0] = j->contact.fdir1[0];
1465 t1[1] = j->contact.fdir1[1];
1466 t1[2] = j->contact.fdir1[2];
1467 dCROSS (t2,=,normal,t1);
1468 }
1469 else {
1470 dPlaneSpace (normal,t1,t2);
1471 }
1472 info->J1l[s+0] = t1[0];
1473 info->J1l[s+1] = t1[1];
1474 info->J1l[s+2] = t1[2];
1475 dCROSS (info->J1a+s,=,c1,t1);
1476 if (j->node[1].body) {
1477 info->J2l[s+0] = -t1[0];
1478 info->J2l[s+1] = -t1[1];
1479 info->J2l[s+2] = -t1[2];
1480 dCROSS (info->J2a+s,= -,c2,t1);
1481 }
1482 // set right hand side
1483 if (j->contact.surface.mode & dContactMotion1) {
1484 info->c[1] = j->contact.surface.motion1;
1485 }
1486 // set LCP bounds and friction index. this depends on the approximation
1487 // mode
1488 info->lo[1] = -j->contact.surface.mu;
1489 info->hi[1] = j->contact.surface.mu;
1490 if (j->contact.surface.mode & dContactApprox1_1) info->findex[1] = 0;
1491
1492 // set slip (constraint force mixing)
1493 if (j->contact.surface.mode & dContactSlip1)
1494 info->cfm[1] = j->contact.surface.slip1;
1495 }
1496
1497 // second friction direction
1498 if (j->the_m >= 3) {
1499 info->J1l[s2+0] = t2[0];
1500 info->J1l[s2+1] = t2[1];
1501 info->J1l[s2+2] = t2[2];
1502 dCROSS (info->J1a+s2,=,c1,t2);
1503 if (j->node[1].body) {
1504 info->J2l[s2+0] = -t2[0];
1505 info->J2l[s2+1] = -t2[1];
1506 info->J2l[s2+2] = -t2[2];
1507 dCROSS (info->J2a+s2,= -,c2,t2);
1508 }
1509 // set right hand side
1510 if (j->contact.surface.mode & dContactMotion2) {
1511 info->c[2] = j->contact.surface.motion2;
1512 }
1513 // set LCP bounds and friction index. this depends on the approximation
1514 // mode
1515 if (j->contact.surface.mode & dContactMu2) {
1516 info->lo[2] = -j->contact.surface.mu2;
1517 info->hi[2] = j->contact.surface.mu2;
1518 }
1519 else {
1520 info->lo[2] = -j->contact.surface.mu;
1521 info->hi[2] = j->contact.surface.mu;
1522 }
1523 if (j->contact.surface.mode & dContactApprox1_2) info->findex[2] = 0;
1524
1525 // set slip (constraint force mixing)
1526 if (j->contact.surface.mode & dContactSlip2)
1527 info->cfm[2] = j->contact.surface.slip2;
1528 }
1529}
1530
1531
1532dxJoint::Vtable __dcontact_vtable = {
1533 sizeof(dxJointContact),
1534 (dxJoint::init_fn*) contactInit,
1535 (dxJoint::getInfo1_fn*) contactGetInfo1,
1536 (dxJoint::getInfo2_fn*) contactGetInfo2,
1537 dJointTypeContact};
1538
1539//****************************************************************************
1540// hinge 2. note that this joint must be attached to two bodies for it to work
1541
1542static dReal measureHinge2Angle (dxJointHinge2 *joint)
1543{
1544 dVector3 a1,a2;
1545 dMULTIPLY0_331 (a1,joint->node[1].body->posr.R,joint->axis2);
1546 dMULTIPLY1_331 (a2,joint->node[0].body->posr.R,a1);
1547 dReal x = dDOT(joint->v1,a2);
1548 dReal y = dDOT(joint->v2,a2);
1549 return -dAtan2 (y,x);
1550}
1551
1552
1553static void hinge2Init (dxJointHinge2 *j)
1554{
1555 dSetZero (j->anchor1,4);
1556 dSetZero (j->anchor2,4);
1557 dSetZero (j->axis1,4);
1558 j->axis1[0] = 1;
1559 dSetZero (j->axis2,4);
1560 j->axis2[1] = 1;
1561 j->c0 = 0;
1562 j->s0 = 0;
1563
1564 dSetZero (j->v1,4);
1565 j->v1[0] = 1;
1566 dSetZero (j->v2,4);
1567 j->v2[1] = 1;
1568
1569 j->limot1.init (j->world);
1570 j->limot2.init (j->world);
1571
1572 j->susp_erp = j->world->global_erp;
1573 j->susp_cfm = j->world->global_cfm;
1574
1575 j->flags |= dJOINT_TWOBODIES;
1576}
1577
1578
1579static void hinge2GetInfo1 (dxJointHinge2 *j, dxJoint::Info1 *info)
1580{
1581 info->m = 4;
1582 info->nub = 4;
1583
1584 // see if we're powered or at a joint limit for axis 1
1585 int atlimit=0;
1586 if ((j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
1587 j->limot1.lostop <= j->limot1.histop) {
1588 dReal angle = measureHinge2Angle (j);
1589 if (j->limot1.testRotationalLimit (angle)) atlimit = 1;
1590 }
1591 if (atlimit || j->limot1.fmax > 0) info->m++;
1592
1593 // see if we're powering axis 2 (we currently never limit this axis)
1594 j->limot2.limit = 0;
1595 if (j->limot2.fmax > 0) info->m++;
1596}
1597
1598
1599// macro that computes ax1,ax2 = axis 1 and 2 in global coordinates (they are
1600// relative to body 1 and 2 initially) and then computes the constrained
1601// rotational axis as the cross product of ax1 and ax2.
1602// the sin and cos of the angle between axis 1 and 2 is computed, this comes
1603// from dot and cross product rules.
1604
1605#define HINGE2_GET_AXIS_INFO(axis,sin_angle,cos_angle) \
1606 dVector3 ax1,ax2; \
1607 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1); \
1608 dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2); \
1609 dCROSS (axis,=,ax1,ax2); \
1610 sin_angle = dSqrt (axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); \
1611 cos_angle = dDOT (ax1,ax2);
1612
1613
1614static void hinge2GetInfo2 (dxJointHinge2 *joint, dxJoint::Info2 *info)
1615{
1616 // get information we need to set the hinge row
1617 dReal s,c;
1618 dVector3 q;
1619 HINGE2_GET_AXIS_INFO (q,s,c);
1620 dNormalize3 (q); // @@@ quicker: divide q by s ?
1621
1622 // set the three ball-and-socket rows (aligned to the suspension axis ax1)
1623 setBall2 (joint,info,joint->anchor1,joint->anchor2,ax1,joint->susp_erp);
1624
1625 // set the hinge row
1626 int s3=3*info->rowskip;
1627 info->J1a[s3+0] = q[0];
1628 info->J1a[s3+1] = q[1];
1629 info->J1a[s3+2] = q[2];
1630 if (joint->node[1].body) {
1631 info->J2a[s3+0] = -q[0];
1632 info->J2a[s3+1] = -q[1];
1633 info->J2a[s3+2] = -q[2];
1634 }
1635
1636 // compute the right hand side for the constrained rotational DOF.
1637 // axis 1 and axis 2 are separated by an angle `theta'. the desired
1638 // separation angle is theta0. sin(theta0) and cos(theta0) are recorded
1639 // in the joint structure. the correcting angular velocity is:
1640 // |angular_velocity| = angle/time = erp*(theta0-theta) / stepsize
1641 // = (erp*fps) * (theta0-theta)
1642 // (theta0-theta) can be computed using the following small-angle-difference
1643 // approximation:
1644 // theta0-theta ~= tan(theta0-theta)
1645 // = sin(theta0-theta)/cos(theta0-theta)
1646 // = (c*s0 - s*c0) / (c*c0 + s*s0)
1647 // = c*s0 - s*c0 assuming c*c0 + s*s0 ~= 1
1648 // where c = cos(theta), s = sin(theta)
1649 // c0 = cos(theta0), s0 = sin(theta0)
1650
1651 dReal k = info->fps * info->erp;
1652 info->c[3] = k * (joint->c0 * s - joint->s0 * c);
1653
1654 // if the axis1 hinge is powered, or has joint limits, add in more stuff
1655 int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
1656
1657 // if the axis2 hinge is powered, add in more stuff
1658 joint->limot2.addLimot (joint,info,row,ax2,1);
1659
1660 // set parameter for the suspension
1661 info->cfm[0] = joint->susp_cfm;
1662}
1663
1664
1665// compute vectors v1 and v2 (embedded in body1), used to measure angle
1666// between body 1 and body 2
1667
1668static void makeHinge2V1andV2 (dxJointHinge2 *joint)
1669{
1670 if (joint->node[0].body) {
1671 // get axis 1 and 2 in global coords
1672 dVector3 ax1,ax2,v;
1673 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
1674 dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
1675
1676 // don't do anything if the axis1 or axis2 vectors are zero or the same
1677 if ((ax1[0]==0 && ax1[1]==0 && ax1[2]==0) ||
1678 (ax2[0]==0 && ax2[1]==0 && ax2[2]==0) ||
1679 (ax1[0]==ax2[0] && ax1[1]==ax2[1] && ax1[2]==ax2[2])) return;
1680
1681 // modify axis 2 so it's perpendicular to axis 1
1682 dReal k = dDOT(ax1,ax2);
1683 for (int i=0; i<3; i++) ax2[i] -= k*ax1[i];
1684 dNormalize3 (ax2);
1685
1686 // make v1 = modified axis2, v2 = axis1 x (modified axis2)
1687 dCROSS (v,=,ax1,ax2);
1688 dMULTIPLY1_331 (joint->v1,joint->node[0].body->posr.R,ax2);
1689 dMULTIPLY1_331 (joint->v2,joint->node[0].body->posr.R,v);
1690 }
1691}
1692
1693
1694void dJointSetHinge2Anchor (dJointID j, dReal x, dReal y, dReal z)
1695{
1696 dxJointHinge2* joint = (dxJointHinge2*)j;
1697 dUASSERT(joint,"bad joint argument");
1698 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1699 setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
1700 makeHinge2V1andV2 (joint);
1701}
1702
1703
1704void dJointSetHinge2Axis1 (dJointID j, dReal x, dReal y, dReal z)
1705{
1706 dxJointHinge2* joint = (dxJointHinge2*)j;
1707 dUASSERT(joint,"bad joint argument");
1708 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1709 if (joint->node[0].body) {
1710 dReal q[4];
1711 q[0] = x;
1712 q[1] = y;
1713 q[2] = z;
1714 q[3] = 0;
1715 dNormalize3 (q);
1716 dMULTIPLY1_331 (joint->axis1,joint->node[0].body->posr.R,q);
1717 joint->axis1[3] = 0;
1718
1719 // compute the sin and cos of the angle between axis 1 and axis 2
1720 dVector3 ax;
1721 HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
1722 }
1723 makeHinge2V1andV2 (joint);
1724}
1725
1726
1727void dJointSetHinge2Axis2 (dJointID j, dReal x, dReal y, dReal z)
1728{
1729 dxJointHinge2* joint = (dxJointHinge2*)j;
1730 dUASSERT(joint,"bad joint argument");
1731 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1732 if (joint->node[1].body) {
1733 dReal q[4];
1734 q[0] = x;
1735 q[1] = y;
1736 q[2] = z;
1737 q[3] = 0;
1738 dNormalize3 (q);
1739 dMULTIPLY1_331 (joint->axis2,joint->node[1].body->posr.R,q);
1740 joint->axis1[3] = 0;
1741
1742 // compute the sin and cos of the angle between axis 1 and axis 2
1743 dVector3 ax;
1744 HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
1745 }
1746 makeHinge2V1andV2 (joint);
1747}
1748
1749
1750void dJointSetHinge2Param (dJointID j, int parameter, dReal value)
1751{
1752 dxJointHinge2* joint = (dxJointHinge2*)j;
1753 dUASSERT(joint,"bad joint argument");
1754 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1755 if ((parameter & 0xff00) == 0x100) {
1756 joint->limot2.set (parameter & 0xff,value);
1757 }
1758 else {
1759 if (parameter == dParamSuspensionERP) joint->susp_erp = value;
1760 else if (parameter == dParamSuspensionCFM) joint->susp_cfm = value;
1761 else joint->limot1.set (parameter,value);
1762 }
1763}
1764
1765
1766void dJointGetHinge2Anchor (dJointID j, dVector3 result)
1767{
1768 dxJointHinge2* joint = (dxJointHinge2*)j;
1769 dUASSERT(joint,"bad joint argument");
1770 dUASSERT(result,"bad result argument");
1771 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1772 if (joint->flags & dJOINT_REVERSE)
1773 getAnchor2 (joint,result,joint->anchor2);
1774 else
1775 getAnchor (joint,result,joint->anchor1);
1776}
1777
1778
1779void dJointGetHinge2Anchor2 (dJointID j, dVector3 result)
1780{
1781 dxJointHinge2* joint = (dxJointHinge2*)j;
1782 dUASSERT(joint,"bad joint argument");
1783 dUASSERT(result,"bad result argument");
1784 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1785 if (joint->flags & dJOINT_REVERSE)
1786 getAnchor (joint,result,joint->anchor1);
1787 else
1788 getAnchor2 (joint,result,joint->anchor2);
1789}
1790
1791
1792void dJointGetHinge2Axis1 (dJointID j, dVector3 result)
1793{
1794 dxJointHinge2* joint = (dxJointHinge2*)j;
1795 dUASSERT(joint,"bad joint argument");
1796 dUASSERT(result,"bad result argument");
1797 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1798 if (joint->node[0].body) {
1799 dMULTIPLY0_331 (result,joint->node[0].body->posr.R,joint->axis1);
1800 }
1801}
1802
1803
1804void dJointGetHinge2Axis2 (dJointID j, dVector3 result)
1805{
1806 dxJointHinge2* joint = (dxJointHinge2*)j;
1807 dUASSERT(joint,"bad joint argument");
1808 dUASSERT(result,"bad result argument");
1809 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1810 if (joint->node[1].body) {
1811 dMULTIPLY0_331 (result,joint->node[1].body->posr.R,joint->axis2);
1812 }
1813}
1814
1815
1816dReal dJointGetHinge2Param (dJointID j, int parameter)
1817{
1818 dxJointHinge2* joint = (dxJointHinge2*)j;
1819 dUASSERT(joint,"bad joint argument");
1820 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1821 if ((parameter & 0xff00) == 0x100) {
1822 return joint->limot2.get (parameter & 0xff);
1823 }
1824 else {
1825 if (parameter == dParamSuspensionERP) return joint->susp_erp;
1826 else if (parameter == dParamSuspensionCFM) return joint->susp_cfm;
1827 else return joint->limot1.get (parameter);
1828 }
1829}
1830
1831
1832dReal dJointGetHinge2Angle1 (dJointID j)
1833{
1834 dxJointHinge2* joint = (dxJointHinge2*)j;
1835 dUASSERT(joint,"bad joint argument");
1836 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1837 if (joint->node[0].body) return measureHinge2Angle (joint);
1838 else return 0;
1839}
1840
1841
1842dReal dJointGetHinge2Angle1Rate (dJointID j)
1843{
1844 dxJointHinge2* joint = (dxJointHinge2*)j;
1845 dUASSERT(joint,"bad joint argument");
1846 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1847 if (joint->node[0].body) {
1848 dVector3 axis;
1849 dMULTIPLY0_331 (axis,joint->node[0].body->posr.R,joint->axis1);
1850 dReal rate = dDOT(axis,joint->node[0].body->avel);
1851 if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
1852 return rate;
1853 }
1854 else return 0;
1855}
1856
1857
1858dReal dJointGetHinge2Angle2Rate (dJointID j)
1859{
1860 dxJointHinge2* joint = (dxJointHinge2*)j;
1861 dUASSERT(joint,"bad joint argument");
1862 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1863 if (joint->node[0].body && joint->node[1].body) {
1864 dVector3 axis;
1865 dMULTIPLY0_331 (axis,joint->node[1].body->posr.R,joint->axis2);
1866 dReal rate = dDOT(axis,joint->node[0].body->avel);
1867 if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
1868 return rate;
1869 }
1870 else return 0;
1871}
1872
1873
1874void dJointAddHinge2Torques (dJointID j, dReal torque1, dReal torque2)
1875{
1876 dxJointHinge2* joint = (dxJointHinge2*)j;
1877 dVector3 axis1, axis2;
1878 dUASSERT(joint,"bad joint argument");
1879 dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
1880
1881 if (joint->node[0].body && joint->node[1].body) {
1882 dMULTIPLY0_331 (axis1,joint->node[0].body->posr.R,joint->axis1);
1883 dMULTIPLY0_331 (axis2,joint->node[1].body->posr.R,joint->axis2);
1884 axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
1885 axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
1886 axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
1887 dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
1888 dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
1889 }
1890}
1891
1892
1893dxJoint::Vtable __dhinge2_vtable = {
1894 sizeof(dxJointHinge2),
1895 (dxJoint::init_fn*) hinge2Init,
1896 (dxJoint::getInfo1_fn*) hinge2GetInfo1,
1897 (dxJoint::getInfo2_fn*) hinge2GetInfo2,
1898 dJointTypeHinge2};
1899
1900//****************************************************************************
1901// universal
1902
1903// I just realized that the universal joint is equivalent to a hinge 2 joint with
1904// perfectly stiff suspension. By comparing the hinge 2 implementation to
1905// the universal implementation, you may be able to improve this
1906// implementation (or, less likely, the hinge2 implementation).
1907
1908static void universalInit (dxJointUniversal *j)
1909{
1910 dSetZero (j->anchor1,4);
1911 dSetZero (j->anchor2,4);
1912 dSetZero (j->axis1,4);
1913 j->axis1[0] = 1;
1914 dSetZero (j->axis2,4);
1915 j->axis2[1] = 1;
1916 dSetZero(j->qrel1,4);
1917 dSetZero(j->qrel2,4);
1918 j->limot1.init (j->world);
1919 j->limot2.init (j->world);
1920}
1921
1922
1923static void getUniversalAxes(dxJointUniversal *joint, dVector3 ax1, dVector3 ax2)
1924{
1925 // This says "ax1 = joint->node[0].body->posr.R * joint->axis1"
1926 dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
1927
1928 if (joint->node[1].body) {
1929 dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
1930 }
1931 else {
1932 ax2[0] = joint->axis2[0];
1933 ax2[1] = joint->axis2[1];
1934 ax2[2] = joint->axis2[2];
1935 }
1936}
1937
1938static void getUniversalAngles(dxJointUniversal *joint, dReal *angle1, dReal *angle2)
1939{
1940 if (joint->node[0].body)
1941 {
1942 // length 1 joint axis in global coordinates, from each body
1943 dVector3 ax1, ax2;
1944 dMatrix3 R;
1945 dQuaternion qcross, qq, qrel;
1946
1947 getUniversalAxes (joint,ax1,ax2);
1948
1949 // It should be possible to get both angles without explicitly
1950 // constructing the rotation matrix of the cross. Basically,
1951 // orientation of the cross about axis1 comes from body 2,
1952 // about axis 2 comes from body 1, and the perpendicular
1953 // axis can come from the two bodies somehow. (We don't really
1954 // want to assume it's 90 degrees, because in general the
1955 // constraints won't be perfectly satisfied, or even very well
1956 // satisfied.)
1957 //
1958 // However, we'd need a version of getHingeAngleFromRElativeQuat()
1959 // that CAN handle when its relative quat is rotated along a direction
1960 // other than the given axis. What I have here works,
1961 // although it's probably much slower than need be.
1962
1963 dRFrom2Axes (R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
1964
1965 dRtoQ (R, qcross);
1966
1967
1968 // This code is essentialy the same as getHingeAngle(), see the comments
1969 // there for details.
1970
1971 // get qrel = relative rotation between node[0] and the cross
1972 dQMultiply1 (qq, joint->node[0].body->q, qcross);
1973 dQMultiply2 (qrel, qq, joint->qrel1);
1974
1975 *angle1 = getHingeAngleFromRelativeQuat(qrel, joint->axis1);
1976
1977 // This is equivalent to
1978 // dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
1979 // You see that the R is constructed from the same 2 axis as for angle1
1980 // but the first and second axis are swapped.
1981 // So we can take the first R and rapply a rotation to it.
1982 // The rotation is around the axis between the 2 axes (ax1 and ax2).
1983 // We do a rotation of 180deg.
1984
1985 dQuaternion qcross2;
1986 // Find the vector between ax1 and ax2 (i.e. in the middle)
1987 // We need to turn around this vector by 180deg
1988
1989 // The 2 axes should be normalize so to find the vector between the 2.
1990 // Add and devide by 2 then normalize or simply normalize
1991 // ax2
1992 // ^
1993 // |
1994 // |
1995 /// *------------> ax1
1996 // We want the vector a 45deg
1997 //
1998 // N.B. We don't need to normalize the ax1 and ax2 since there are
1999 // normalized when we set them.
2000
2001 // We set the quaternion q = [cos(theta), dir*sin(theta)] = [w, x, y, Z]
2002 qrel[0] = 0; // equivalent to cos(Pi/2)
2003 qrel[1] = ax1[0] + ax2[0]; // equivalent to x*sin(Pi/2); since sin(Pi/2) = 1
2004 qrel[2] = ax1[1] + ax2[1];
2005 qrel[3] = ax1[2] + ax2[2];
2006
2007 dReal l = dRecip(sqrt(qrel[1]*qrel[1] + qrel[2]*qrel[2] + qrel[3]*qrel[3]));
2008 qrel[1] *= l;
2009 qrel[2] *= l;
2010 qrel[3] *= l;
2011
2012 dQMultiply0 (qcross2, qrel, qcross);
2013
2014 if (joint->node[1].body) {
2015 dQMultiply1 (qq, joint->node[1].body->q, qcross2);
2016 dQMultiply2 (qrel, qq, joint->qrel2);
2017 }
2018 else {
2019 // pretend joint->node[1].body->q is the identity
2020 dQMultiply2 (qrel, qcross2, joint->qrel2);
2021 }
2022
2023 *angle2 = - getHingeAngleFromRelativeQuat(qrel, joint->axis2);
2024
2025 }
2026 else
2027 {
2028 *angle1 = 0;
2029 *angle2 = 0;
2030 }
2031}
2032
2033static dReal getUniversalAngle1(dxJointUniversal *joint)
2034{
2035 if (joint->node[0].body) {
2036 // length 1 joint axis in global coordinates, from each body
2037 dVector3 ax1, ax2;
2038 dMatrix3 R;
2039 dQuaternion qcross, qq, qrel;
2040
2041 getUniversalAxes (joint,ax1,ax2);
2042
2043 // It should be possible to get both angles without explicitly
2044 // constructing the rotation matrix of the cross. Basically,
2045 // orientation of the cross about axis1 comes from body 2,
2046 // about axis 2 comes from body 1, and the perpendicular
2047 // axis can come from the two bodies somehow. (We don't really
2048 // want to assume it's 90 degrees, because in general the
2049 // constraints won't be perfectly satisfied, or even very well
2050 // satisfied.)
2051 //
2052 // However, we'd need a version of getHingeAngleFromRElativeQuat()
2053 // that CAN handle when its relative quat is rotated along a direction
2054 // other than the given axis. What I have here works,
2055 // although it's probably much slower than need be.
2056
2057 dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
2058 dRtoQ (R,qcross);
2059
2060 // This code is essential the same as getHingeAngle(), see the comments
2061 // there for details.
2062
2063 // get qrel = relative rotation between node[0] and the cross
2064 dQMultiply1 (qq,joint->node[0].body->q,qcross);
2065 dQMultiply2 (qrel,qq,joint->qrel1);
2066
2067 return getHingeAngleFromRelativeQuat(qrel, joint->axis1);
2068 }
2069 return 0;
2070}
2071
2072
2073static dReal getUniversalAngle2(dxJointUniversal *joint)
2074{
2075 if (joint->node[0].body) {
2076 // length 1 joint axis in global coordinates, from each body
2077 dVector3 ax1, ax2;
2078 dMatrix3 R;
2079 dQuaternion qcross, qq, qrel;
2080
2081 getUniversalAxes (joint,ax1,ax2);
2082
2083 // It should be possible to get both angles without explicitly
2084 // constructing the rotation matrix of the cross. Basically,
2085 // orientation of the cross about axis1 comes from body 2,
2086 // about axis 2 comes from body 1, and the perpendicular
2087 // axis can come from the two bodies somehow. (We don't really
2088 // want to assume it's 90 degrees, because in general the
2089 // constraints won't be perfectly satisfied, or even very well
2090 // satisfied.)
2091 //
2092 // However, we'd need a version of getHingeAngleFromRElativeQuat()
2093 // that CAN handle when its relative quat is rotated along a direction
2094 // other than the given axis. What I have here works,
2095 // although it's probably much slower than need be.
2096
2097 dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
2098 dRtoQ(R, qcross);
2099
2100 if (joint->node[1].body) {
2101 dQMultiply1 (qq, joint->node[1].body->q, qcross);
2102 dQMultiply2 (qrel,qq,joint->qrel2);
2103 }
2104 else {
2105 // pretend joint->node[1].body->q is the identity
2106 dQMultiply2 (qrel,qcross, joint->qrel2);
2107 }
2108
2109 return - getHingeAngleFromRelativeQuat(qrel, joint->axis2);
2110 }
2111 return 0;
2112}
2113
2114
2115static void universalGetInfo1 (dxJointUniversal *j, dxJoint::Info1 *info)
2116{
2117 info->nub = 4;
2118 info->m = 4;
2119
2120 // see if we're powered or at a joint limit.
2121 bool constraint1 = j->limot1.fmax > 0;
2122 bool constraint2 = j->limot2.fmax > 0;
2123
2124 bool limiting1 = (j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
2125 j->limot1.lostop <= j->limot1.histop;
2126 bool limiting2 = (j->limot2.lostop >= -M_PI || j->limot2.histop <= M_PI) &&
2127 j->limot2.lostop <= j->limot2.histop;
2128
2129 // We need to call testRotationLimit() even if we're motored, since it
2130 // records the result.
2131 if (limiting1 || limiting2) {
2132 dReal angle1, angle2;
2133 getUniversalAngles (j, &angle1, &angle2);
2134 if (limiting1 && j->limot1.testRotationalLimit (angle1)) constraint1 = true;
2135 if (limiting2 && j->limot2.testRotationalLimit (angle2)) constraint2 = true;
2136 }
2137 if (constraint1)
2138 info->m++;
2139 if (constraint2)
2140 info->m++;
2141}
2142
2143
2144static void universalGetInfo2 (dxJointUniversal *joint, dxJoint::Info2 *info)
2145{
2146 // set the three ball-and-socket rows
2147 setBall (joint,info,joint->anchor1,joint->anchor2);
2148
2149 // set the universal joint row. the angular velocity about an axis
2150 // perpendicular to both joint axes should be equal. thus the constraint
2151 // equation is
2152 // p*w1 - p*w2 = 0
2153 // where p is a vector normal to both joint axes, and w1 and w2
2154 // are the angular velocity vectors of the two bodies.
2155
2156 // length 1 joint axis in global coordinates, from each body
2157 dVector3 ax1, ax2;
2158 dVector3 ax2_temp;
2159 // length 1 vector perpendicular to ax1 and ax2. Neither body can rotate
2160 // about this.
2161 dVector3 p;
2162 dReal k;
2163
2164 getUniversalAxes(joint, ax1, ax2);
2165 k = dDOT(ax1, ax2);
2166 ax2_temp[0] = ax2[0] - k*ax1[0];
2167 ax2_temp[1] = ax2[1] - k*ax1[1];
2168 ax2_temp[2] = ax2[2] - k*ax1[2];
2169 dCROSS(p, =, ax1, ax2_temp);
2170 dNormalize3(p);
2171
2172 int s3=3*info->rowskip;
2173
2174 info->J1a[s3+0] = p[0];
2175 info->J1a[s3+1] = p[1];
2176 info->J1a[s3+2] = p[2];
2177
2178 if (joint->node[1].body) {
2179 info->J2a[s3+0] = -p[0];
2180 info->J2a[s3+1] = -p[1];
2181 info->J2a[s3+2] = -p[2];
2182 }
2183
2184 // compute the right hand side of the constraint equation. set relative
2185 // body velocities along p to bring the axes back to perpendicular.
2186 // If ax1, ax2 are unit length joint axes as computed from body1 and
2187 // body2, we need to rotate both bodies along the axis p. If theta
2188 // is the angle between ax1 and ax2, we need an angular velocity
2189 // along p to cover the angle erp * (theta - Pi/2) in one step:
2190 //
2191 // |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize
2192 // = (erp*fps) * (theta - Pi/2)
2193 //
2194 // if theta is close to Pi/2,
2195 // theta - Pi/2 ~= cos(theta), so
2196 // |angular_velocity| ~= (erp*fps) * (ax1 dot ax2)
2197
2198 info->c[3] = info->fps * info->erp * - dDOT(ax1, ax2);
2199
2200 // if the first angle is powered, or has joint limits, add in the stuff
2201 int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
2202
2203 // if the second angle is powered, or has joint limits, add in more stuff
2204 joint->limot2.addLimot (joint,info,row,ax2,1);
2205}
2206
2207
2208static void universalComputeInitialRelativeRotations (dxJointUniversal *joint)
2209{
2210 if (joint->node[0].body) {
2211 dVector3 ax1, ax2;
2212 dMatrix3 R;
2213 dQuaternion qcross;
2214
2215 getUniversalAxes(joint, ax1, ax2);
2216
2217 // Axis 1.
2218 dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
2219 dRtoQ(R, qcross);
2220 dQMultiply1 (joint->qrel1, joint->node[0].body->q, qcross);
2221
2222 // Axis 2.
2223 dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
2224 dRtoQ(R, qcross);
2225 if (joint->node[1].body) {
2226 dQMultiply1 (joint->qrel2, joint->node[1].body->q, qcross);
2227 }
2228 else {
2229 // set joint->qrel to qcross
2230 for (int i=0; i<4; i++) joint->qrel2[i] = qcross[i];
2231 }
2232 }
2233}
2234
2235
2236void dJointSetUniversalAnchor (dJointID j, dReal x, dReal y, dReal z)
2237{
2238 dxJointUniversal* joint = (dxJointUniversal*)j;
2239 dUASSERT(joint,"bad joint argument");
2240 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2241 setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
2242 universalComputeInitialRelativeRotations(joint);
2243}
2244
2245
2246void dJointSetUniversalAxis1 (dJointID j, dReal x, dReal y, dReal z)
2247{
2248 dxJointUniversal* joint = (dxJointUniversal*)j;
2249 dUASSERT(joint,"bad joint argument");
2250 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2251 if (joint->flags & dJOINT_REVERSE)
2252 setAxes (joint,x,y,z,NULL,joint->axis2);
2253 else
2254 setAxes (joint,x,y,z,joint->axis1,NULL);
2255 universalComputeInitialRelativeRotations(joint);
2256}
2257
2258
2259void dJointSetUniversalAxis2 (dJointID j, dReal x, dReal y, dReal z)
2260{
2261 dxJointUniversal* joint = (dxJointUniversal*)j;
2262 dUASSERT(joint,"bad joint argument");
2263 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2264 if (joint->flags & dJOINT_REVERSE)
2265 setAxes (joint,x,y,z,joint->axis1,NULL);
2266 else
2267 setAxes (joint,x,y,z,NULL,joint->axis2);
2268 universalComputeInitialRelativeRotations(joint);
2269}
2270
2271
2272void dJointGetUniversalAnchor (dJointID j, dVector3 result)
2273{
2274 dxJointUniversal* joint = (dxJointUniversal*)j;
2275 dUASSERT(joint,"bad joint argument");
2276 dUASSERT(result,"bad result argument");
2277 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2278 if (joint->flags & dJOINT_REVERSE)
2279 getAnchor2 (joint,result,joint->anchor2);
2280 else
2281 getAnchor (joint,result,joint->anchor1);
2282}
2283
2284
2285void dJointGetUniversalAnchor2 (dJointID j, dVector3 result)
2286{
2287 dxJointUniversal* joint = (dxJointUniversal*)j;
2288 dUASSERT(joint,"bad joint argument");
2289 dUASSERT(result,"bad result argument");
2290 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2291 if (joint->flags & dJOINT_REVERSE)
2292 getAnchor (joint,result,joint->anchor1);
2293 else
2294 getAnchor2 (joint,result,joint->anchor2);
2295}
2296
2297
2298void dJointGetUniversalAxis1 (dJointID j, dVector3 result)
2299{
2300 dxJointUniversal* joint = (dxJointUniversal*)j;
2301 dUASSERT(joint,"bad joint argument");
2302 dUASSERT(result,"bad result argument");
2303 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2304 if (joint->flags & dJOINT_REVERSE)
2305 getAxis2 (joint,result,joint->axis2);
2306 else
2307 getAxis (joint,result,joint->axis1);
2308}
2309
2310
2311void dJointGetUniversalAxis2 (dJointID j, dVector3 result)
2312{
2313 dxJointUniversal* joint = (dxJointUniversal*)j;
2314 dUASSERT(joint,"bad joint argument");
2315 dUASSERT(result,"bad result argument");
2316 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2317 if (joint->flags & dJOINT_REVERSE)
2318 getAxis (joint,result,joint->axis1);
2319 else
2320 getAxis2 (joint,result,joint->axis2);
2321}
2322
2323
2324void dJointSetUniversalParam (dJointID j, int parameter, dReal value)
2325{
2326 dxJointUniversal* joint = (dxJointUniversal*)j;
2327 dUASSERT(joint,"bad joint argument");
2328 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2329 if ((parameter & 0xff00) == 0x100) {
2330 joint->limot2.set (parameter & 0xff,value);
2331 }
2332 else {
2333 joint->limot1.set (parameter,value);
2334 }
2335}
2336
2337
2338dReal dJointGetUniversalParam (dJointID j, int parameter)
2339{
2340 dxJointUniversal* joint = (dxJointUniversal*)j;
2341 dUASSERT(joint,"bad joint argument");
2342 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2343 if ((parameter & 0xff00) == 0x100) {
2344 return joint->limot2.get (parameter & 0xff);
2345 }
2346 else {
2347 return joint->limot1.get (parameter);
2348 }
2349}
2350
2351void dJointGetUniversalAngles (dJointID j, dReal *angle1, dReal *angle2)
2352{
2353 dxJointUniversal* joint = (dxJointUniversal*)j;
2354 dUASSERT(joint,"bad joint argument");
2355 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2356 if (joint->flags & dJOINT_REVERSE)
2357 return getUniversalAngles (joint, angle2, angle1);
2358 else
2359 return getUniversalAngles (joint, angle1, angle2);
2360}
2361
2362
2363dReal dJointGetUniversalAngle1 (dJointID j)
2364{
2365 dxJointUniversal* joint = (dxJointUniversal*)j;
2366 dUASSERT(joint,"bad joint argument");
2367 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2368 if (joint->flags & dJOINT_REVERSE)
2369 return getUniversalAngle2 (joint);
2370 else
2371 return getUniversalAngle1 (joint);
2372}
2373
2374
2375dReal dJointGetUniversalAngle2 (dJointID j)
2376{
2377 dxJointUniversal* joint = (dxJointUniversal*)j;
2378 dUASSERT(joint,"bad joint argument");
2379 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2380 if (joint->flags & dJOINT_REVERSE)
2381 return getUniversalAngle1 (joint);
2382 else
2383 return getUniversalAngle2 (joint);
2384}
2385
2386
2387dReal dJointGetUniversalAngle1Rate (dJointID j)
2388{
2389 dxJointUniversal* joint = (dxJointUniversal*)j;
2390 dUASSERT(joint,"bad joint argument");
2391 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2392
2393 if (joint->node[0].body) {
2394 dVector3 axis;
2395
2396 if (joint->flags & dJOINT_REVERSE)
2397 getAxis2 (joint,axis,joint->axis2);
2398 else
2399 getAxis (joint,axis,joint->axis1);
2400
2401 dReal rate = dDOT(axis, joint->node[0].body->avel);
2402 if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
2403 return rate;
2404 }
2405 return 0;
2406}
2407
2408
2409dReal dJointGetUniversalAngle2Rate (dJointID j)
2410{
2411 dxJointUniversal* joint = (dxJointUniversal*)j;
2412 dUASSERT(joint,"bad joint argument");
2413 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2414
2415 if (joint->node[0].body) {
2416 dVector3 axis;
2417
2418 if (joint->flags & dJOINT_REVERSE)
2419 getAxis (joint,axis,joint->axis1);
2420 else
2421 getAxis2 (joint,axis,joint->axis2);
2422
2423 dReal rate = dDOT(axis, joint->node[0].body->avel);
2424 if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
2425 return rate;
2426 }
2427 return 0;
2428}
2429
2430
2431void dJointAddUniversalTorques (dJointID j, dReal torque1, dReal torque2)
2432{
2433 dxJointUniversal* joint = (dxJointUniversal*)j;
2434 dVector3 axis1, axis2;
2435 dAASSERT(joint);
2436 dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
2437
2438 if (joint->flags & dJOINT_REVERSE) {
2439 dReal temp = torque1;
2440 torque1 = - torque2;
2441 torque2 = - temp;
2442 }
2443
2444 getAxis (joint,axis1,joint->axis1);
2445 getAxis2 (joint,axis2,joint->axis2);
2446 axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
2447 axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
2448 axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
2449
2450 if (joint->node[0].body != 0)
2451 dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
2452 if (joint->node[1].body != 0)
2453 dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
2454}
2455
2456
2457
2458
2459
2460dxJoint::Vtable __duniversal_vtable = {
2461 sizeof(dxJointUniversal),
2462 (dxJoint::init_fn*) universalInit,
2463 (dxJoint::getInfo1_fn*) universalGetInfo1,
2464 (dxJoint::getInfo2_fn*) universalGetInfo2,
2465 dJointTypeUniversal};
2466
2467
2468
2469//****************************************************************************
2470// Prismatic and Rotoide
2471
2472static void PRInit (dxJointPR *j)
2473{
2474 // Default Position
2475 // Z^
2476 // | Body 1 P R Body2
2477 // |+---------+ _ _ +-----------+
2478 // || |----|----(_)--------+ |
2479 // |+---------+ - +-----------+
2480 // |
2481 // X.-----------------------------------------> Y
2482 // N.B. X is comming out of the page
2483 dSetZero (j->anchor2,4);
2484
2485 dSetZero (j->axisR1,4);
2486 j->axisR1[0] = 1;
2487 dSetZero (j->axisR2,4);
2488 j->axisR2[0] = 1;
2489
2490 dSetZero (j->axisP1,4);
2491 j->axisP1[1] = 1;
2492 dSetZero (j->qrel,4);
2493 dSetZero (j->offset,4);
2494
2495 j->limotR.init (j->world);
2496 j->limotP.init (j->world);
2497}
2498
2499
2500dReal dJointGetPRPosition (dJointID j)
2501{
2502 dxJointPR* joint = (dxJointPR*)j;
2503 dUASSERT(joint,"bad joint argument");
2504 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
2505
2506 dVector3 q;
2507 // get the offset in global coordinates
2508 dMULTIPLY0_331 (q,joint->node[0].body->posr.R,joint->offset);
2509
2510 if (joint->node[1].body) {
2511 dVector3 anchor2;
2512
2513 // get the anchor2 in global coordinates
2514 dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R,joint->anchor2);
2515
2516 q[0] = ( (joint->node[0].body->posr.pos[0] + q[0]) -
2517 (joint->node[1].body->posr.pos[0] + anchor2[0]) );
2518 q[1] = ( (joint->node[0].body->posr.pos[1] + q[1]) -
2519 (joint->node[1].body->posr.pos[1] + anchor2[1]) );
2520 q[2] = ( (joint->node[0].body->posr.pos[2] + q[2]) -
2521 (joint->node[1].body->posr.pos[2] + anchor2[2]) );
2522
2523 }
2524 else {
2525 //N.B. When there is no body 2 the joint->anchor2 is already in
2526 // global coordinates
2527
2528 q[0] = ( (joint->node[0].body->posr.pos[0] + q[0]) -
2529 (joint->anchor2[0]) );
2530 q[1] = ( (joint->node[0].body->posr.pos[1] + q[1]) -
2531 (joint->anchor2[1]) );
2532 q[2] = ( (joint->node[0].body->posr.pos[2] + q[2]) -
2533 (joint->anchor2[2]) );
2534
2535 }
2536
2537 dVector3 axP;
2538 // get prismatic axis in global coordinates
2539 dMULTIPLY0_331 (axP,joint->node[0].body->posr.R,joint->axisP1);
2540
2541 return dDOT(axP, q);
2542}
2543
2544
2545dReal dJointGetPRPositionRate (dJointID j)
2546{
2547 dxJointPR* joint = (dxJointPR*)j;
2548 dUASSERT(joint,"bad joint argument");
2549 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
2550
2551 if (joint->node[0].body) {
2552 // We want to find the rate of change of the prismatic part of the joint
2553 // We can find it by looking at the speed difference between body1 and the
2554 // anchor point.
2555
2556 // r will be used to find the distance between body1 and the anchor point
2557 dVector3 r;
2558 if (joint->node[1].body) {
2559 // Find joint->anchor2 in global coordinates
2560 dVector3 anchor2;
2561 dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R,joint->anchor2);
2562
2563 r[0] = joint->node[0].body->posr.pos[0] - anchor2[0];
2564 r[1] = joint->node[0].body->posr.pos[1] - anchor2[1];
2565 r[2] = joint->node[0].body->posr.pos[2] - anchor2[2];
2566 }
2567 else {
2568 //N.B. When there is no body 2 the joint->anchor2 is already in
2569 // global coordinates
2570 r[0] = joint->node[0].body->posr.pos[0] - joint->anchor2[0];
2571 r[1] = joint->node[0].body->posr.pos[1] - joint->anchor2[1];
2572 r[2] = joint->node[0].body->posr.pos[2] - joint->anchor2[2];
2573 }
2574
2575 // The body1 can have velocity coming from the rotation of
2576 // the rotoide axis. We need to remove this.
2577
2578 // Take only the angular rotation coming from the rotation
2579 // of the rotoide articulation
2580 // N.B. Body1 and Body2 should have the same rotation along axis
2581 // other than the rotoide axis.
2582 dVector3 angular;
2583 dMULTIPLY0_331 (angular,joint->node[0].body->posr.R,joint->axisR1);
2584 dReal omega = dDOT(angular, joint->node[0].body->avel);
2585 angular[0] *= omega;
2586 angular[1] *= omega;
2587 angular[2] *= omega;
2588
2589 // Find the contribution of the angular rotation to the linear speed
2590 // N.B. We do vel = r X w instead of vel = w x r to have vel negative
2591 // since we want to remove it from the linear velocity of the body
2592 dVector3 lvel1;
2593 dCROSS(lvel1, =, r, angular);
2594
2595 lvel1[0] += joint->node[0].body->lvel[0];
2596 lvel1[1] += joint->node[0].body->lvel[1];
2597 lvel1[2] += joint->node[0].body->lvel[2];
2598
2599 // Since we want rate of change along the prismatic axis
2600 // get axisP1 in global coordinates and get the component
2601 // along this axis only
2602 dVector3 axP1;
2603 dMULTIPLY0_331 (axP1,joint->node[0].body->posr.R,joint->axisP1);
2604 return dDOT(axP1, lvel1);
2605 }
2606
2607 return 0.0;
2608}
2609
2610
2611
2612static void PRGetInfo1 (dxJointPR *j, dxJoint::Info1 *info)
2613{
2614 info->m = 4;
2615 info->nub = 4;
2616
2617 bool added = false;
2618
2619 added = false;
2620 // see if the prismatic articulation is powered
2621 if (j->limotP.fmax > 0)
2622 {
2623 added = true;
2624 (info->m)++; // powered needs an extra constraint row
2625 }
2626
2627 // see if we're at a joint limit.
2628 j->limotP.limit = 0;
2629 if ((j->limotP.lostop > -dInfinity || j->limotP.histop < dInfinity) &&
2630 j->limotP.lostop <= j->limotP.histop) {
2631 // measure joint position
2632 dReal pos = dJointGetPRPosition (j);
2633 if (pos <= j->limotP.lostop) {
2634 j->limotP.limit = 1;
2635 j->limotP.limit_err = pos - j->limotP.lostop;
2636 if (!added)
2637 (info->m)++;
2638 }
2639
2640 if (pos >= j->limotP.histop) {
2641 j->limotP.limit = 2;
2642 j->limotP.limit_err = pos - j->limotP.histop;
2643 if (!added)
2644 (info->m)++;
2645 }
2646 }
2647
2648}
2649
2650
2651
2652static void PRGetInfo2 (dxJointPR *joint, dxJoint::Info2 *info)
2653{
2654 int s = info->rowskip;
2655 int s2= 2*s;
2656 int s3= 3*s;
2657 int s4= 4*s;
2658
2659 dReal k = info->fps * info->erp;
2660
2661
2662 dVector3 q; // plane space of axP and after that axR
2663
2664 // pull out pos and R for both bodies. also get the `connection'
2665 // vector pos2-pos1.
2666
2667 dReal *pos1,*pos2,*R1,*R2;
2668 pos1 = joint->node[0].body->posr.pos;
2669 R1 = joint->node[0].body->posr.R;
2670 if (joint->node[1].body) {
2671 pos2 = joint->node[1].body->posr.pos;
2672 R2 = joint->node[1].body->posr.R;
2673 }
2674 else {
2675 // pos2 = 0; // N.B. We can do that to be safe but it is no necessary
2676 // R2 = 0; // N.B. We can do that to be safe but it is no necessary
2677 }
2678
2679
2680 dVector3 axP; // Axis of the prismatic joint in global frame
2681 dMULTIPLY0_331 (axP, R1, joint->axisP1);
2682
2683 // distance between the body1 and the anchor2 in global frame
2684 // Calculated in the same way as the offset
2685 dVector3 dist;
2686
2687 if (joint->node[1].body)
2688 {
2689 dMULTIPLY0_331 (dist, R2, joint->anchor2);
2690 dist[0] += pos2[0] - pos1[0];
2691 dist[1] += pos2[1] - pos1[1];
2692 dist[2] += pos2[2] - pos1[2];
2693 }
2694 else {
2695 dist[0] = joint->anchor2[0] - pos1[0];
2696 dist[1] = joint->anchor2[1] - pos1[1];
2697 dist[2] = joint->anchor2[2] - pos1[2];
2698 }
2699
2700
2701 // ======================================================================
2702 // Work on the Rotoide part (i.e. row 0, 1 and maybe 4 if rotoide powered
2703
2704 // Set the two rotoide rows. The rotoide axis should be the only unconstrained
2705 // rotational axis, the angular velocity of the two bodies perpendicular to
2706 // the rotoide axis should be equal. Thus the constraint equations are
2707 // p*w1 - p*w2 = 0
2708 // q*w1 - q*w2 = 0
2709 // where p and q are unit vectors normal to the rotoide axis, and w1 and w2
2710 // are the angular velocity vectors of the two bodies.
2711 dVector3 ax1;
2712 dMULTIPLY0_331 (ax1, joint->node[0].body->posr.R, joint->axisR1);
2713 dCROSS(q , =, ax1, axP);
2714
2715 info->J1a[0] = axP[0];
2716 info->J1a[1] = axP[1];
2717 info->J1a[2] = axP[2];
2718 info->J1a[s+0] = q[0];
2719 info->J1a[s+1] = q[1];
2720 info->J1a[s+2] = q[2];
2721
2722 if (joint->node[1].body) {
2723 info->J2a[0] = -axP[0];
2724 info->J2a[1] = -axP[1];
2725 info->J2a[2] = -axP[2];
2726 info->J2a[s+0] = -q[0];
2727 info->J2a[s+1] = -q[1];
2728 info->J2a[s+2] = -q[2];
2729 }
2730
2731
2732 // Compute the right hand side of the constraint equation set. Relative
2733 // body velocities along p and q to bring the rotoide back into alignment.
2734 // ax1,ax2 are the unit length rotoide axes of body1 and body2 in world frame.
2735 // We need to rotate both bodies along the axis u = (ax1 x ax2).
2736 // if `theta' is the angle between ax1 and ax2, we need an angular velocity
2737 // along u to cover angle erp*theta in one step :
2738 // |angular_velocity| = angle/time = erp*theta / stepsize
2739 // = (erp*fps) * theta
2740 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
2741 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
2742 // ...as ax1 and ax2 are unit length. if theta is smallish,
2743 // theta ~= sin(theta), so
2744 // angular_velocity = (erp*fps) * (ax1 x ax2)
2745 // ax1 x ax2 is in the plane space of ax1, so we project the angular
2746 // velocity to p and q to find the right hand side.
2747
2748 dVector3 ax2;
2749 if (joint->node[1].body) {
2750 dMULTIPLY0_331 (ax2, R2, joint->axisR2);
2751 }
2752 else {
2753 ax2[0] = joint->axisR2[0];
2754 ax2[1] = joint->axisR2[1];
2755 ax2[2] = joint->axisR2[2];
2756 }
2757
2758 dVector3 b;
2759 dCROSS (b,=,ax1, ax2);
2760 info->c[0] = k * dDOT(b, axP);
2761 info->c[1] = k * dDOT(b, q);
2762
2763
2764
2765 // ==========================
2766 // Work on the Prismatic part (i.e row 2,3 and 4 if only the prismatic is powered
2767 // or 5 if rotoide and prismatic powered
2768
2769 // two rows. we want: vel2 = vel1 + w1 x c ... but this would
2770 // result in three equations, so we project along the planespace vectors
2771 // so that sliding along the prismatic axis is disregarded. for symmetry we
2772 // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2.
2773
2774 // p1 + R1 dist' = p2 + R2 anchor2' ## OLD ## p1 + R1 anchor1' = p2 + R2 dist'
2775 // 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
2776 // v_p is speed of prismatic joint (i.e. elongation rate)
2777 // Since the constraints are perpendicular to v_p we have:
2778 // p dot v_p = 0 and q dot v_p = 0
2779 // ax1 dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
2780 // q dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
2781 // ==
2782 // 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
2783 // since a . (b x c) = - b . (a x c) = - (a x c) . b
2784 // and a x b = - b x a
2785 // ax1 . v1 - ax1 x dist . w1 - ax1 . v2 - (- ax1 x anchor2 . w2) = 0
2786 // ax1 . v1 + dist x ax1 . w1 - ax1 . v2 - anchor2 x ax1 . w2 = 0
2787 // Coeff for 1er line of: J1l => ax1, J2l => -ax1
2788 // Coeff for 2er line of: J1l => q, J2l => -q
2789 // Coeff for 1er line of: J1a => dist x ax1, J2a => - anchor2 x ax1
2790 // Coeff for 2er line of: J1a => dist x q, J2a => - anchor2 x q
2791
2792
2793 dCROSS ((info->J1a)+s2, = , dist, ax1);
2794
2795 dCROSS ((info->J1a)+s3, = , dist, q);
2796
2797
2798 info->J1l[s2+0] = ax1[0];
2799 info->J1l[s2+1] = ax1[1];
2800 info->J1l[s2+2] = ax1[2];
2801
2802 info->J1l[s3+0] = q[0];
2803 info->J1l[s3+1] = q[1];
2804 info->J1l[s3+2] = q[2];
2805
2806 if (joint->node[1].body) {
2807 dVector3 anchor2;
2808
2809 // Calculate anchor2 in world coordinate
2810 dMULTIPLY0_331 (anchor2, R2, joint->anchor2);
2811
2812 // ax2 x anchor2 instead of anchor2 x ax2 since we want the negative value
2813 dCROSS ((info->J2a)+s2, = , ax2, anchor2); // since ax1 == ax2
2814
2815 // The cross product is in reverse order since we want the negative value
2816 dCROSS ((info->J2a)+s3, = , q, anchor2);
2817
2818 info->J2l[s2+0] = -ax1[0];
2819 info->J2l[s2+1] = -ax1[1];
2820 info->J2l[s2+2] = -ax1[2];
2821
2822 info->J2l[s3+0] = -q[0];
2823 info->J2l[s3+1] = -q[1];
2824 info->J2l[s3+2] = -q[2];
2825 }
2826
2827
2828 // We want to make correction for motion not in the line of the axisP
2829 // We calculate the displacement w.r.t. the anchor pt.
2830 //
2831 // compute the elements 2 and 3 of right hand side.
2832 // we want to align the offset point (in body 2's frame) with the center of body 1.
2833 // The position should be the same when we are not along the prismatic axis
2834 dVector3 err;
2835 dMULTIPLY0_331 (err, R1, joint->offset);
2836 err[0] += dist[0];
2837 err[1] += dist[1];
2838 err[2] += dist[2];
2839 info->c[2] = k * dDOT(ax1, err);
2840 info->c[3] = k * dDOT(q, err);
2841
2842 // Here we can't use addLimot because of some assumption in the function
2843 int powered = joint->limotP.fmax > 0;
2844 if (powered || joint->limotP.limit) {
2845 info->J1l[s4+0] = axP[0];
2846 info->J1l[s4+1] = axP[1];
2847 info->J1l[s4+2] = axP[2];
2848 if (joint->node[1].body) {
2849 info->J2l[s4+0] = -axP[0];
2850 info->J2l[s4+1] = -axP[1];
2851 info->J2l[s4+2] = -axP[2];
2852 }
2853 // linear limot torque decoupling step:
2854 //
2855 // if this is a linear limot (e.g. from a slider), we have to be careful
2856 // that the linear constraint forces (+/- ax1) applied to the two bodies
2857 // do not create a torque couple. in other words, the points that the
2858 // constraint force is applied at must lie along the same ax1 axis.
2859 // a torque couple will result in powered or limited slider-jointed free
2860 // bodies from gaining angular momentum.
2861 // the solution used here is to apply the constraint forces at the point
2862 // halfway between the body centers. there is no penalty (other than an
2863 // extra tiny bit of computation) in doing this adjustment. note that we
2864 // only need to do this if the constraint connects two bodies.
2865
2866 dVector3 ltd; // Linear Torque Decoupling vector (a torque)
2867 if (joint->node[1].body) {
2868 dVector3 c;
2869 c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
2870 c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
2871 c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
2872 dReal val = dDOT(q, c);
2873 c[0] -= val * c[0];
2874 c[1] -= val * c[1];
2875 c[2] -= val * c[2];
2876
2877 dCROSS (ltd,=,c,axP);
2878 info->J1a[s4+0] = ltd[0];
2879 info->J1a[s4+1] = ltd[1];
2880 info->J1a[s4+2] = ltd[2];
2881 info->J2a[s4+0] = ltd[0];
2882 info->J2a[s4+1] = ltd[1];
2883 info->J2a[s4+2] = ltd[2];
2884 }
2885
2886 // if we're limited low and high simultaneously, the joint motor is
2887 // ineffective
2888 if (joint->limotP.limit && (joint->limotP.lostop == joint->limotP.histop))
2889 powered = 0;
2890
2891 int row = 4;
2892 if (powered) {
2893 info->cfm[row] = joint->limotP.normal_cfm;
2894 if (!joint->limotP.limit) {
2895 info->c[row] = joint->limotP.vel;
2896 info->lo[row] = -joint->limotP.fmax;
2897 info->hi[row] = joint->limotP.fmax;
2898 }
2899 else {
2900 // the joint is at a limit, AND is being powered. if the joint is
2901 // being powered into the limit then we apply the maximum motor force
2902 // in that direction, because the motor is working against the
2903 // immovable limit. if the joint is being powered away from the limit
2904 // then we have problems because actually we need *two* lcp
2905 // constraints to handle this case. so we fake it and apply some
2906 // fraction of the maximum force. the fraction to use can be set as
2907 // a fudge factor.
2908
2909 dReal fm = joint->limotP.fmax;
2910 dReal vel = joint->limotP.vel;
2911 int limit = joint->limotP.limit;
2912 if ((vel > 0) || (vel==0 && limit==2)) fm = -fm;
2913
2914 // if we're powering away from the limit, apply the fudge factor
2915 if ((limit==1 && vel > 0) || (limit==2 && vel < 0))
2916 fm *= joint->limotP.fudge_factor;
2917
2918
2919 dBodyAddForce (joint->node[0].body,-fm*axP[0],-fm*axP[1],-fm*axP[2]);
2920
2921 if (joint->node[1].body) {
2922 dBodyAddForce (joint->node[1].body,fm*axP[0],fm*axP[1],fm*axP[2]);
2923
2924 // linear limot torque decoupling step: refer to above discussion
2925 dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1],
2926 -fm*ltd[2]);
2927 dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1],
2928 -fm*ltd[2]);
2929 }
2930 }
2931 }
2932
2933 if (joint->limotP.limit) {
2934 dReal k = info->fps * joint->limotP.stop_erp;
2935 info->c[row] = -k * joint->limotP.limit_err;
2936 info->cfm[row] = joint->limotP.stop_cfm;
2937
2938 if (joint->limotP.lostop == joint->limotP.histop) {
2939 // limited low and high simultaneously
2940 info->lo[row] = -dInfinity;
2941 info->hi[row] = dInfinity;
2942 }
2943 else {
2944 if (joint->limotP.limit == 1) {
2945 // low limit
2946 info->lo[row] = 0;
2947 info->hi[row] = dInfinity;
2948 }
2949 else {
2950 // high limit
2951 info->lo[row] = -dInfinity;
2952 info->hi[row] = 0;
2953 }
2954
2955 // deal with bounce
2956 if (joint->limotP.bounce > 0) {
2957 // calculate joint velocity
2958 dReal vel;
2959 vel = dDOT(joint->node[0].body->lvel, axP);
2960 if (joint->node[1].body)
2961 vel -= dDOT(joint->node[1].body->lvel, axP);
2962
2963 // only apply bounce if the velocity is incoming, and if the
2964 // resulting c[] exceeds what we already have.
2965 if (joint->limotP.limit == 1) {
2966 // low limit
2967 if (vel < 0) {
2968 dReal newc = -joint->limotP.bounce * vel;
2969 if (newc > info->c[row]) info->c[row] = newc;
2970 }
2971 }
2972 else {
2973 // high limit - all those computations are reversed
2974 if (vel > 0) {
2975 dReal newc = -joint->limotP.bounce * vel;
2976 if (newc < info->c[row]) info->c[row] = newc;
2977 }
2978 }
2979 }
2980 }
2981 }
2982 }
2983}
2984
2985
2986// compute initial relative rotation body1 -> body2, or env -> body1
2987static void PRComputeInitialRelativeRotation (dxJointPR *joint)
2988{
2989 if (joint->node[0].body) {
2990 if (joint->node[1].body) {
2991 dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
2992 }
2993 else {
2994 // set joint->qrel to the transpose of the first body q
2995 joint->qrel[0] = joint->node[0].body->q[0];
2996 for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
2997 // WARNING do we need the - in -joint->node[0].body->q[i]; or not
2998 }
2999 }
3000}
3001
3002void dJointSetPRAnchor (dJointID j, dReal x, dReal y, dReal z)
3003{
3004 dxJointPR* joint = (dxJointPR*)j;
3005 dUASSERT(joint,"bad joint argument");
3006 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3007
3008 dVector3 dummy;
3009 setAnchors (joint,x,y,z,dummy,joint->anchor2);
3010}
3011
3012
3013void dJointSetPRAxis1 (dJointID j, dReal x, dReal y, dReal z)
3014{
3015 dxJointPR* joint = (dxJointPR*)j;
3016 dUASSERT(joint,"bad joint argument");
3017 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3018
3019 setAxes (joint,x,y,z,joint->axisP1, 0);
3020
3021 PRComputeInitialRelativeRotation (joint);
3022
3023 // compute initial relative rotation body1 -> body2, or env -> body1
3024 // also compute distance between anchor of body1 w.r.t center of body 2
3025 dVector3 c;
3026 if (joint->node[1].body) {
3027 dVector3 anchor2;
3028 dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R, joint->anchor2);
3029
3030 c[0] = ( joint->node[1].body->posr.pos[0] + anchor2[0] -
3031 joint->node[0].body->posr.pos[0] );
3032 c[1] = ( joint->node[1].body->posr.pos[1] + anchor2[1] -
3033 joint->node[0].body->posr.pos[1] );
3034 c[2] = ( joint->node[1].body->posr.pos[2] + anchor2[2] -
3035 joint->node[0].body->posr.pos[2] );
3036 }
3037 else if (joint->node[0].body) {
3038 c[0] = joint->anchor2[0] - joint->node[0].body->posr.pos[0];
3039 c[1] = joint->anchor2[1] - joint->node[0].body->posr.pos[1];
3040 c[2] = joint->anchor2[2] - joint->node[0].body->posr.pos[2];
3041 }
3042 else
3043 {
3044 joint->offset[0] = joint->anchor2[0];
3045 joint->offset[1] = joint->anchor2[1];
3046 joint->offset[2] = joint->anchor2[2];
3047
3048 return;
3049 }
3050
3051
3052 dMULTIPLY1_331 (joint->offset,joint->node[0].body->posr.R,c);
3053}
3054
3055
3056void dJointSetPRAxis2 (dJointID j, dReal x, dReal y, dReal z)
3057{
3058 dxJointPR* joint = (dxJointPR*)j;
3059 dUASSERT(joint,"bad joint argument");
3060 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3061 setAxes (joint,x,y,z,joint->axisR1,joint->axisR2);
3062 PRComputeInitialRelativeRotation (joint);
3063}
3064
3065
3066void dJointSetPRParam (dJointID j, int parameter, dReal value)
3067{
3068 dxJointPR* joint = (dxJointPR*)j;
3069 dUASSERT(joint,"bad joint argument");
3070 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3071 if ((parameter & 0xff00) == 0x100) {
3072 joint->limotR.set (parameter,value);
3073 }
3074 else {
3075 joint->limotP.set (parameter & 0xff,value);
3076 }
3077}
3078
3079void dJointGetPRAnchor (dJointID j, dVector3 result)
3080{
3081 dxJointPR* joint = (dxJointPR*)j;
3082 dUASSERT(joint,"bad joint argument");
3083 dUASSERT(result,"bad result argument");
3084 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3085
3086 if (joint->node[1].body)
3087 getAnchor2 (joint,result,joint->anchor2);
3088 else
3089 {
3090 result[0] = joint->anchor2[0];
3091 result[1] = joint->anchor2[1];
3092 result[2] = joint->anchor2[2];
3093 }
3094
3095}
3096
3097void dJointGetPRAxis1 (dJointID j, dVector3 result)
3098{
3099 dxJointPR* joint = (dxJointPR*)j;
3100 dUASSERT(joint,"bad joint argument");
3101 dUASSERT(result,"bad result argument");
3102 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3103 getAxis(joint, result, joint->axisP1);
3104}
3105
3106void dJointGetPRAxis2 (dJointID j, dVector3 result)
3107{
3108 dxJointPR* joint = (dxJointPR*)j;
3109 dUASSERT(joint,"bad joint argument");
3110 dUASSERT(result,"bad result argument");
3111 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3112 getAxis(joint, result, joint->axisR1);
3113}
3114
3115dReal dJointGetPRParam (dJointID j, int parameter)
3116{
3117 dxJointPR* joint = (dxJointPR*)j;
3118 dUASSERT(joint,"bad joint argument");
3119 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not Prismatic and Rotoide");
3120 if ((parameter & 0xff00) == 0x100) {
3121 return joint->limotR.get (parameter & 0xff);
3122 }
3123 else {
3124 return joint->limotP.get (parameter);
3125 }
3126}
3127
3128void dJointAddPRTorque (dJointID j, dReal torque)
3129{
3130 dxJointPR* joint = (dxJointPR*)j;
3131 dVector3 axis;
3132 dAASSERT(joint);
3133 dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
3134
3135 if (joint->flags & dJOINT_REVERSE)
3136 torque = -torque;
3137
3138 getAxis (joint,axis,joint->axisR1);
3139 axis[0] *= torque;
3140 axis[1] *= torque;
3141 axis[2] *= torque;
3142
3143 if (joint->node[0].body != 0)
3144 dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
3145 if (joint->node[1].body != 0)
3146 dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
3147}
3148
3149
3150dxJoint::Vtable __dPR_vtable = {
3151 sizeof(dxJointPR),
3152 (dxJoint::init_fn*) PRInit,
3153 (dxJoint::getInfo1_fn*) PRGetInfo1,
3154 (dxJoint::getInfo2_fn*) PRGetInfo2,
3155 dJointTypePR
3156};
3157
3158
3159//****************************************************************************
3160// angular motor
3161
3162static void amotorInit (dxJointAMotor *j)
3163{
3164 int i;
3165 j->num = 0;
3166 j->mode = dAMotorUser;
3167 for (i=0; i<3; i++) {
3168 j->rel[i] = 0;
3169 dSetZero (j->axis[i],4);
3170 j->limot[i].init (j->world);
3171 j->angle[i] = 0;
3172 }
3173 dSetZero (j->reference1,4);
3174 dSetZero (j->reference2,4);
3175}
3176
3177
3178// compute the 3 axes in global coordinates
3179
3180static void amotorComputeGlobalAxes (dxJointAMotor *joint, dVector3 ax[3])
3181{
3182 if (joint->mode == dAMotorEuler) {
3183 // special handling for euler mode
3184 dMULTIPLY0_331 (ax[0],joint->node[0].body->posr.R,joint->axis[0]);
3185 if (joint->node[1].body) {
3186 dMULTIPLY0_331 (ax[2],joint->node[1].body->posr.R,joint->axis[2]);
3187 }
3188 else {
3189 ax[2][0] = joint->axis[2][0];
3190 ax[2][1] = joint->axis[2][1];
3191 ax[2][2] = joint->axis[2][2];
3192 }
3193 dCROSS (ax[1],=,ax[2],ax[0]);
3194 dNormalize3 (ax[1]);
3195 }
3196 else {
3197 for (int i=0; i < joint->num; i++) {
3198 if (joint->rel[i] == 1) {
3199 // relative to b1
3200 dMULTIPLY0_331 (ax[i],joint->node[0].body->posr.R,joint->axis[i]);
3201 }
3202 else if (joint->rel[i] == 2) {
3203 // relative to b2
3204 if (joint->node[1].body) { // jds: don't assert, just ignore
3205 dMULTIPLY0_331 (ax[i],joint->node[1].body->posr.R,joint->axis[i]);
3206 }
3207 }
3208 else {
3209 // global - just copy it
3210 ax[i][0] = joint->axis[i][0];
3211 ax[i][1] = joint->axis[i][1];
3212 ax[i][2] = joint->axis[i][2];
3213 }
3214 }
3215 }
3216}
3217
3218
3219static void amotorComputeEulerAngles (dxJointAMotor *joint, dVector3 ax[3])
3220{
3221 // assumptions:
3222 // global axes already calculated --> ax
3223 // axis[0] is relative to body 1 --> global ax[0]
3224 // axis[2] is relative to body 2 --> global ax[2]
3225 // ax[1] = ax[2] x ax[0]
3226 // original ax[0] and ax[2] are perpendicular
3227 // reference1 is perpendicular to ax[0] (in body 1 frame)
3228 // reference2 is perpendicular to ax[2] (in body 2 frame)
3229 // all ax[] and reference vectors are unit length
3230
3231 // calculate references in global frame
3232 dVector3 ref1,ref2;
3233 dMULTIPLY0_331 (ref1,joint->node[0].body->posr.R,joint->reference1);
3234 if (joint->node[1].body) {
3235 dMULTIPLY0_331 (ref2,joint->node[1].body->posr.R,joint->reference2);
3236 }
3237 else {
3238 ref2[0] = joint->reference2[0];
3239 ref2[1] = joint->reference2[1];
3240 ref2[2] = joint->reference2[2];
3241 }
3242
3243 // get q perpendicular to both ax[0] and ref1, get first euler angle
3244 dVector3 q;
3245 dCROSS (q,=,ax[0],ref1);
3246 joint->angle[0] = -dAtan2 (dDOT(ax[2],q),dDOT(ax[2],ref1));
3247
3248 // get q perpendicular to both ax[0] and ax[1], get second euler angle
3249 dCROSS (q,=,ax[0],ax[1]);
3250 joint->angle[1] = -dAtan2 (dDOT(ax[2],ax[0]),dDOT(ax[2],q));
3251
3252 // get q perpendicular to both ax[1] and ax[2], get third euler angle
3253 dCROSS (q,=,ax[1],ax[2]);
3254 joint->angle[2] = -dAtan2 (dDOT(ref2,ax[1]), dDOT(ref2,q));
3255}
3256
3257
3258// set the reference vectors as follows:
3259// * reference1 = current axis[2] relative to body 1
3260// * reference2 = current axis[0] relative to body 2
3261// this assumes that:
3262// * axis[0] is relative to body 1
3263// * axis[2] is relative to body 2
3264
3265static void amotorSetEulerReferenceVectors (dxJointAMotor *j)
3266{
3267 if (j->node[0].body && j->node[1].body) {
3268 dVector3 r; // axis[2] and axis[0] in global coordinates
3269 dMULTIPLY0_331 (r,j->node[1].body->posr.R,j->axis[2]);
3270 dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,r);
3271 dMULTIPLY0_331 (r,j->node[0].body->posr.R,j->axis[0]);
3272 dMULTIPLY1_331 (j->reference2,j->node[1].body->posr.R,r);
3273 }
3274
3275 else { // jds
3276 // else if (j->node[0].body) {
3277 // dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,j->axis[2]);
3278 // dMULTIPLY0_331 (j->reference2,j->node[0].body->posr.R,j->axis[0]);
3279
3280 // We want to handle angular motors attached to passive geoms
3281 dVector3 r; // axis[2] and axis[0] in global coordinates
3282 r[0] = j->axis[2][0]; r[1] = j->axis[2][1]; r[2] = j->axis[2][2]; r[3] = j->axis[2][3];
3283 dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,r);
3284 dMULTIPLY0_331 (r,j->node[0].body->posr.R,j->axis[0]);
3285 j->reference2[0] += r[0]; j->reference2[1] += r[1];
3286 j->reference2[2] += r[2]; j->reference2[3] += r[3];
3287 }
3288}
3289
3290
3291static void amotorGetInfo1 (dxJointAMotor *j, dxJoint::Info1 *info)
3292{
3293 info->m = 0;
3294 info->nub = 0;
3295
3296 // compute the axes and angles, if in euler mode
3297 if (j->mode == dAMotorEuler) {
3298 dVector3 ax[3];
3299 amotorComputeGlobalAxes (j,ax);
3300 amotorComputeEulerAngles (j,ax);
3301 }
3302
3303 // see if we're powered or at a joint limit for each axis
3304 for (int i=0; i < j->num; i++) {
3305 if (j->limot[i].testRotationalLimit (j->angle[i]) ||
3306 j->limot[i].fmax > 0) {
3307 info->m++;
3308 }
3309 }
3310}
3311
3312
3313static void amotorGetInfo2 (dxJointAMotor *joint, dxJoint::Info2 *info)
3314{
3315 int i;
3316
3317 // compute the axes (if not global)
3318 dVector3 ax[3];
3319 amotorComputeGlobalAxes (joint,ax);
3320
3321 // in euler angle mode we do not actually constrain the angular velocity
3322 // along the axes axis[0] and axis[2] (although we do use axis[1]) :
3323 //
3324 // to get constrain w2-w1 along ...not
3325 // ------ --------------------- ------
3326 // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
3327 // d(angle[1])/dt = 0 ax[1]
3328 // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
3329 //
3330 // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
3331 // to prove the result for angle[0], write the expression for angle[0] from
3332 // GetInfo1 then take the derivative. to prove this for angle[2] it is
3333 // easier to take the euler rate expression for d(angle[2])/dt with respect
3334 // to the components of w and set that to 0.
3335
3336 dVector3 *axptr[3];
3337 axptr[0] = &ax[0];
3338 axptr[1] = &ax[1];
3339 axptr[2] = &ax[2];
3340
3341 dVector3 ax0_cross_ax1;
3342 dVector3 ax1_cross_ax2;
3343 if (joint->mode == dAMotorEuler) {
3344 dCROSS (ax0_cross_ax1,=,ax[0],ax[1]);
3345 axptr[2] = &ax0_cross_ax1;
3346 dCROSS (ax1_cross_ax2,=,ax[1],ax[2]);
3347 axptr[0] = &ax1_cross_ax2;
3348 }
3349
3350 int row=0;
3351 for (i=0; i < joint->num; i++) {
3352 row += joint->limot[i].addLimot (joint,info,row,*(axptr[i]),1);
3353 }
3354}
3355
3356
3357void dJointSetAMotorNumAxes (dJointID j, int num)
3358{
3359 dxJointAMotor* joint = (dxJointAMotor*)j;
3360 dAASSERT(joint && num >= 0 && num <= 3);
3361 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3362 if (joint->mode == dAMotorEuler) {
3363 joint->num = 3;
3364 }
3365 else {
3366 if (num < 0) num = 0;
3367 if (num > 3) num = 3;
3368 joint->num = num;
3369 }
3370}
3371
3372
3373void dJointSetAMotorAxis (dJointID j, int anum, int rel, dReal x, dReal y, dReal z)
3374{
3375 dxJointAMotor* joint = (dxJointAMotor*)j;
3376 dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2);
3377 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3378 dUASSERT(!(!joint->node[1].body && (joint->flags & dJOINT_REVERSE) && rel == 1),"no first body, can't set axis rel=1");
3379 dUASSERT(!(!joint->node[1].body && !(joint->flags & dJOINT_REVERSE) && rel == 2),"no second body, can't set axis rel=2");
3380 if (anum < 0) anum = 0;
3381 if (anum > 2) anum = 2;
3382
3383 // adjust rel to match the internal body order
3384 if (!joint->node[1].body && rel==2) rel = 1;
3385
3386 joint->rel[anum] = rel;
3387
3388 // x,y,z is always in global coordinates regardless of rel, so we may have
3389 // to convert it to be relative to a body
3390 dVector3 r;
3391 r[0] = x;
3392 r[1] = y;
3393 r[2] = z;
3394 r[3] = 0;
3395 if (rel > 0) {
3396 if (rel==1) {
3397 dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->posr.R,r);
3398 }
3399 else {
3400 // don't assert; handle the case of attachment to a bodiless geom
3401 if (joint->node[1].body) { // jds
3402 dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->posr.R,r);
3403 }
3404 else {
3405 joint->axis[anum][0] = r[0]; joint->axis[anum][1] = r[1];
3406 joint->axis[anum][2] = r[2]; joint->axis[anum][3] = r[3];
3407 }
3408 }
3409 }
3410 else {
3411 joint->axis[anum][0] = r[0];
3412 joint->axis[anum][1] = r[1];
3413 joint->axis[anum][2] = r[2];
3414 }
3415 dNormalize3 (joint->axis[anum]);
3416 if (joint->mode == dAMotorEuler) amotorSetEulerReferenceVectors (joint);
3417}
3418
3419
3420void dJointSetAMotorAngle (dJointID j, int anum, dReal angle)
3421{
3422 dxJointAMotor* joint = (dxJointAMotor*)j;
3423 dAASSERT(joint && anum >= 0 && anum < 3);
3424 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3425 if (joint->mode == dAMotorUser) {
3426 if (anum < 0) anum = 0;
3427 if (anum > 3) anum = 3;
3428 joint->angle[anum] = angle;
3429 }
3430}
3431
3432
3433void dJointSetAMotorParam (dJointID j, int parameter, dReal value)
3434{
3435 dxJointAMotor* joint = (dxJointAMotor*)j;
3436 dAASSERT(joint);
3437 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3438 int anum = parameter >> 8;
3439 if (anum < 0) anum = 0;
3440 if (anum > 2) anum = 2;
3441 parameter &= 0xff;
3442 joint->limot[anum].set (parameter, value);
3443}
3444
3445
3446void dJointSetAMotorMode (dJointID j, int mode)
3447{
3448 dxJointAMotor* joint = (dxJointAMotor*)j;
3449 dAASSERT(joint);
3450 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3451 joint->mode = mode;
3452 if (joint->mode == dAMotorEuler) {
3453 joint->num = 3;
3454 amotorSetEulerReferenceVectors (joint);
3455 }
3456}
3457
3458
3459int dJointGetAMotorNumAxes (dJointID j)
3460{
3461 dxJointAMotor* joint = (dxJointAMotor*)j;
3462 dAASSERT(joint);
3463 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3464 return joint->num;
3465}
3466
3467
3468void dJointGetAMotorAxis (dJointID j, int anum, dVector3 result)
3469{
3470 dxJointAMotor* joint = (dxJointAMotor*)j;
3471 dAASSERT(joint && anum >= 0 && anum < 3);
3472 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3473 if (anum < 0) anum = 0;
3474 if (anum > 2) anum = 2;
3475 if (joint->rel[anum] > 0) {
3476 if (joint->rel[anum]==1) {
3477 dMULTIPLY0_331 (result,joint->node[0].body->posr.R,joint->axis[anum]);
3478 }
3479 else {
3480 if (joint->node[1].body) { // jds
3481 dMULTIPLY0_331 (result,joint->node[1].body->posr.R,joint->axis[anum]);
3482 }
3483 else {
3484 result[0] = joint->axis[anum][0]; result[1] = joint->axis[anum][1];
3485 result[2] = joint->axis[anum][2]; result[3] = joint->axis[anum][3];
3486 }
3487 }
3488 }
3489 else {
3490 result[0] = joint->axis[anum][0];
3491 result[1] = joint->axis[anum][1];
3492 result[2] = joint->axis[anum][2];
3493 }
3494}
3495
3496
3497int dJointGetAMotorAxisRel (dJointID j, int anum)
3498{
3499 dxJointAMotor* joint = (dxJointAMotor*)j;
3500 dAASSERT(joint && anum >= 0 && anum < 3);
3501 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3502 if (anum < 0) anum = 0;
3503 if (anum > 2) anum = 2;
3504 return joint->rel[anum];
3505}
3506
3507
3508dReal dJointGetAMotorAngle (dJointID j, int anum)
3509{
3510 dxJointAMotor* joint = (dxJointAMotor*)j;
3511 dAASSERT(joint && anum >= 0 && anum < 3);
3512 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3513 if (anum < 0) anum = 0;
3514 if (anum > 3) anum = 3;
3515 return joint->angle[anum];
3516}
3517
3518
3519dReal dJointGetAMotorAngleRate (dJointID j, int anum)
3520{
3521 dxJointAMotor* joint = (dxJointAMotor*)j;
3522 // @@@
3523 dDebug (0,"not yet implemented");
3524 return 0;
3525}
3526
3527
3528dReal dJointGetAMotorParam (dJointID j, int parameter)
3529{
3530 dxJointAMotor* joint = (dxJointAMotor*)j;
3531 dAASSERT(joint);
3532 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3533 int anum = parameter >> 8;
3534 if (anum < 0) anum = 0;
3535 if (anum > 2) anum = 2;
3536 parameter &= 0xff;
3537 return joint->limot[anum].get (parameter);
3538}
3539
3540
3541int dJointGetAMotorMode (dJointID j)
3542{
3543 dxJointAMotor* joint = (dxJointAMotor*)j;
3544 dAASSERT(joint);
3545 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3546 return joint->mode;
3547}
3548
3549
3550void dJointAddAMotorTorques (dJointID j, dReal torque1, dReal torque2, dReal torque3)
3551{
3552 dxJointAMotor* joint = (dxJointAMotor*)j;
3553 dVector3 axes[3];
3554 dAASSERT(joint);
3555 dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
3556
3557 if (joint->num == 0)
3558 return;
3559 dUASSERT((joint->flags & dJOINT_REVERSE) == 0, "dJointAddAMotorTorques not yet implemented for reverse AMotor joints");
3560
3561 amotorComputeGlobalAxes (joint,axes);
3562 axes[0][0] *= torque1;
3563 axes[0][1] *= torque1;
3564 axes[0][2] *= torque1;
3565 if (joint->num >= 2) {
3566 axes[0][0] += axes[1][0] * torque2;
3567 axes[0][1] += axes[1][1] * torque2;
3568 axes[0][2] += axes[1][2] * torque2;
3569 if (joint->num >= 3) {
3570 axes[0][0] += axes[2][0] * torque3;
3571 axes[0][1] += axes[2][1] * torque3;
3572 axes[0][2] += axes[2][2] * torque3;
3573 }
3574 }
3575
3576 if (joint->node[0].body != 0)
3577 dBodyAddTorque (joint->node[0].body,axes[0][0],axes[0][1],axes[0][2]);
3578 if (joint->node[1].body != 0)
3579 dBodyAddTorque(joint->node[1].body, -axes[0][0], -axes[0][1], -axes[0][2]);
3580}
3581
3582
3583dxJoint::Vtable __damotor_vtable = {
3584 sizeof(dxJointAMotor),
3585 (dxJoint::init_fn*) amotorInit,
3586 (dxJoint::getInfo1_fn*) amotorGetInfo1,
3587 (dxJoint::getInfo2_fn*) amotorGetInfo2,
3588 dJointTypeAMotor};
3589
3590
3591
3592//****************************************************************************
3593// lmotor joint
3594static void lmotorInit (dxJointLMotor *j)
3595{
3596 int i;
3597 j->num = 0;
3598 for (i=0;i<3;i++) {
3599 dSetZero(j->axis[i],4);
3600 j->limot[i].init(j->world);
3601 }
3602}
3603
3604static void lmotorComputeGlobalAxes (dxJointLMotor *joint, dVector3 ax[3])
3605{
3606 for (int i=0; i< joint->num; i++) {
3607 if (joint->rel[i] == 1) {
3608 dMULTIPLY0_331 (ax[i],joint->node[0].body->posr.R,joint->axis[i]);
3609 }
3610 else if (joint->rel[i] == 2) {
3611 if (joint->node[1].body) { // jds: don't assert, just ignore
3612 dMULTIPLY0_331 (ax[i],joint->node[1].body->posr.R,joint->axis[i]);
3613 }
3614 } else {
3615 ax[i][0] = joint->axis[i][0];
3616 ax[i][1] = joint->axis[i][1];
3617 ax[i][2] = joint->axis[i][2];
3618 }
3619 }
3620}
3621
3622static void lmotorGetInfo1 (dxJointLMotor *j, dxJoint::Info1 *info)
3623{
3624 info->m = 0;
3625 info->nub = 0;
3626 for (int i=0; i < j->num; i++) {
3627 if (j->limot[i].fmax > 0) {
3628 info->m++;
3629 }
3630 }
3631}
3632
3633static void lmotorGetInfo2 (dxJointLMotor *joint, dxJoint::Info2 *info)
3634{
3635 int row=0;
3636 dVector3 ax[3];
3637 lmotorComputeGlobalAxes(joint, ax);
3638
3639 for (int i=0;i<joint->num;i++) {
3640 row += joint->limot[i].addLimot(joint,info,row,ax[i], 0);
3641 }
3642}
3643
3644void dJointSetLMotorAxis (dJointID j, int anum, int rel, dReal x, dReal y, dReal z)
3645{
3646 dxJointLMotor* joint = (dxJointLMotor*)j;
3647//for now we are ignoring rel!
3648 dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2);
3649 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3650 if (anum < 0) anum = 0;
3651 if (anum > 2) anum = 2;
3652
3653 if (!joint->node[1].body && rel==2) rel = 1; //ref 1
3654
3655 joint->rel[anum] = rel;
3656
3657 dVector3 r;
3658 r[0] = x;
3659 r[1] = y;
3660 r[2] = z;
3661 r[3] = 0;
3662 if (rel > 0) {
3663 if (rel==1) {
3664 dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->posr.R,r);
3665 } else {
3666 //second body has to exists thanks to ref 1 line
3667 dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->posr.R,r);
3668 }
3669 } else {
3670 joint->axis[anum][0] = r[0];
3671 joint->axis[anum][1] = r[1];
3672 joint->axis[anum][2] = r[2];
3673 }
3674
3675 dNormalize3 (joint->axis[anum]);
3676}
3677
3678void dJointSetLMotorNumAxes (dJointID j, int num)
3679{
3680 dxJointLMotor* joint = (dxJointLMotor*)j;
3681 dAASSERT(joint && num >= 0 && num <= 3);
3682 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3683 if (num < 0) num = 0;
3684 if (num > 3) num = 3;
3685 joint->num = num;
3686}
3687
3688void dJointSetLMotorParam (dJointID j, int parameter, dReal value)
3689{
3690 dxJointLMotor* joint = (dxJointLMotor*)j;
3691 dAASSERT(joint);
3692 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3693 int anum = parameter >> 8;
3694 if (anum < 0) anum = 0;
3695 if (anum > 2) anum = 2;
3696 parameter &= 0xff;
3697 joint->limot[anum].set (parameter, value);
3698}
3699
3700int dJointGetLMotorNumAxes (dJointID j)
3701{
3702 dxJointLMotor* joint = (dxJointLMotor*)j;
3703 dAASSERT(joint);
3704 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3705 return joint->num;
3706}
3707
3708
3709void dJointGetLMotorAxis (dJointID j, int anum, dVector3 result)
3710{
3711 dxJointLMotor* joint = (dxJointLMotor*)j;
3712 dAASSERT(joint && anum >= 0 && anum < 3);
3713 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3714 if (anum < 0) anum = 0;
3715 if (anum > 2) anum = 2;
3716 result[0] = joint->axis[anum][0];
3717 result[1] = joint->axis[anum][1];
3718 result[2] = joint->axis[anum][2];
3719}
3720
3721dReal dJointGetLMotorParam (dJointID j, int parameter)
3722{
3723 dxJointLMotor* joint = (dxJointLMotor*)j;
3724 dAASSERT(joint);
3725 dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
3726 int anum = parameter >> 8;
3727 if (anum < 0) anum = 0;
3728 if (anum > 2) anum = 2;
3729 parameter &= 0xff;
3730 return joint->limot[anum].get (parameter);
3731}
3732
3733dxJoint::Vtable __dlmotor_vtable = {
3734 sizeof(dxJointLMotor),
3735 (dxJoint::init_fn*) lmotorInit,
3736 (dxJoint::getInfo1_fn*) lmotorGetInfo1,
3737 (dxJoint::getInfo2_fn*) lmotorGetInfo2,
3738 dJointTypeLMotor
3739};
3740
3741
3742//****************************************************************************
3743// fixed joint
3744
3745static void fixedInit (dxJointFixed *j)
3746{
3747 dSetZero (j->offset,4);
3748 dSetZero (j->qrel,4);
3749 j->erp = j->world->global_erp;
3750 j->cfm = j->world->global_cfm;
3751}
3752
3753
3754static void fixedGetInfo1 (dxJointFixed *j, dxJoint::Info1 *info)
3755{
3756 info->m = 6;
3757 info->nub = 6;
3758}
3759
3760
3761static void fixedGetInfo2 (dxJointFixed *joint, dxJoint::Info2 *info)
3762{
3763 int s = info->rowskip;
3764
3765 // Three rows for orientation
3766 setFixedOrientation(joint, info, joint->qrel, 3);
3767
3768 // Three rows for position.
3769 // set jacobian
3770 info->J1l[0] = 1;
3771 info->J1l[s+1] = 1;
3772 info->J1l[2*s+2] = 1;
3773
3774 info->erp = joint->erp;
3775 info->cfm[0] = joint->cfm;
3776 info->cfm[1] = joint->cfm;
3777 info->cfm[2] = joint->cfm;
3778
3779 dVector3 ofs;
3780 dMULTIPLY0_331 (ofs,joint->node[0].body->posr.R,joint->offset);
3781 if (joint->node[1].body) {
3782 dCROSSMAT (info->J1a,ofs,s,+,-);
3783 info->J2l[0] = -1;
3784 info->J2l[s+1] = -1;
3785 info->J2l[2*s+2] = -1;
3786 }
3787
3788 // set right hand side for the first three rows (linear)
3789 dReal k = info->fps * info->erp;
3790 if (joint->node[1].body) {
3791 for (int j=0; j<3; j++)
3792 info->c[j] = k * (joint->node[1].body->posr.pos[j] -
3793 joint->node[0].body->posr.pos[j] + ofs[j]);
3794 }
3795 else {
3796 for (int j=0; j<3; j++)
3797 info->c[j] = k * (joint->offset[j] - joint->node[0].body->posr.pos[j]);
3798 }
3799}
3800
3801
3802void dJointSetFixed (dJointID j)
3803{
3804 dxJointFixed* joint = (dxJointFixed*)j;
3805 dUASSERT(joint,"bad joint argument");
3806 dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not fixed");
3807 int i;
3808
3809 // This code is taken from sJointSetSliderAxis(), we should really put the
3810 // common code in its own function.
3811 // compute the offset between the bodies
3812 if (joint->node[0].body) {
3813 if (joint->node[1].body) {
3814 dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
3815 dReal ofs[4];
3816 for (i=0; i<4; i++) ofs[i] = joint->node[0].body->posr.pos[i];
3817 for (i=0; i<4; i++) ofs[i] -= joint->node[1].body->posr.pos[i];
3818 dMULTIPLY1_331 (joint->offset,joint->node[0].body->posr.R,ofs);
3819 }
3820 else {
3821 // set joint->qrel to the transpose of the first body's q
3822 joint->qrel[0] = joint->node[0].body->q[0];
3823 for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
3824 for (i=0; i<4; i++) joint->offset[i] = joint->node[0].body->posr.pos[i];
3825 }
3826 }
3827}
3828
3829void dxJointFixed::set (int num, dReal value)
3830{
3831 switch (num) {
3832 case dParamCFM:
3833 cfm = value;
3834 break;
3835 case dParamERP:
3836 erp = value;
3837 break;
3838 }
3839}
3840
3841
3842dReal dxJointFixed::get (int num)
3843{
3844 switch (num) {
3845 case dParamCFM:
3846 return cfm;
3847 case dParamERP:
3848 return erp;
3849 default:
3850 return 0;
3851 }
3852}
3853
3854
3855void dJointSetFixedParam (dJointID j, int parameter, dReal value)
3856{
3857 dxJointFixed* joint = (dxJointFixed*)j;
3858 dUASSERT(joint,"bad joint argument");
3859 dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not a fixed joint");
3860 joint->set (parameter,value);
3861}
3862
3863
3864dReal dJointGetFixedParam (dJointID j, int parameter)
3865{
3866 dxJointFixed* joint = (dxJointFixed*)j;
3867 dUASSERT(joint,"bad joint argument");
3868 dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not a fixed joint");
3869 return joint->get (parameter);
3870}
3871
3872
3873dxJoint::Vtable __dfixed_vtable = {
3874 sizeof(dxJointFixed),
3875 (dxJoint::init_fn*) fixedInit,
3876 (dxJoint::getInfo1_fn*) fixedGetInfo1,
3877 (dxJoint::getInfo2_fn*) fixedGetInfo2,
3878 dJointTypeFixed};
3879
3880//****************************************************************************
3881// null joint
3882
3883static void nullGetInfo1 (dxJointNull *j, dxJoint::Info1 *info)
3884{
3885 info->m = 0;
3886 info->nub = 0;
3887}
3888
3889
3890static void nullGetInfo2 (dxJointNull *joint, dxJoint::Info2 *info)
3891{
3892 dDebug (0,"this should never get called");
3893}
3894
3895
3896dxJoint::Vtable __dnull_vtable = {
3897 sizeof(dxJointNull),
3898 (dxJoint::init_fn*) 0,
3899 (dxJoint::getInfo1_fn*) nullGetInfo1,
3900 (dxJoint::getInfo2_fn*) nullGetInfo2,
3901 dJointTypeNull};
3902
3903
3904
3905
3906/*
3907 This code is part of the Plane2D ODE joint
3908 by psero@gmx.de
3909 Wed Apr 23 18:53:43 CEST 2003
3910
3911 Add this code to the file: ode/src/joint.cpp
3912*/
3913
3914
3915# define VoXYZ(v1, o1, x, y, z) \
3916 ( \
3917 (v1)[0] o1 (x), \
3918 (v1)[1] o1 (y), \
3919 (v1)[2] o1 (z) \
3920 )
3921
3922static dReal Midentity[3][3] =
3923 {
3924 { 1, 0, 0 },
3925 { 0, 1, 0 },
3926 { 0, 0, 1, }
3927 };
3928
3929
3930
3931static void plane2dInit (dxJointPlane2D *j)
3932/*********************************************/
3933{
3934 /* MINFO ("plane2dInit ()"); */
3935 j->motor_x.init (j->world);
3936 j->motor_y.init (j->world);
3937 j->motor_angle.init (j->world);
3938}
3939
3940
3941
3942static void plane2dGetInfo1 (dxJointPlane2D *j, dxJoint::Info1 *info)
3943/***********************************************************************/
3944{
3945 /* MINFO ("plane2dGetInfo1 ()"); */
3946
3947 info->nub = 3;
3948 info->m = 3;
3949
3950 if (j->motor_x.fmax > 0)
3951 j->row_motor_x = info->m ++;
3952 if (j->motor_y.fmax > 0)
3953 j->row_motor_y = info->m ++;
3954 if (j->motor_angle.fmax > 0)
3955 j->row_motor_angle = info->m ++;
3956}
3957
3958
3959
3960static void plane2dGetInfo2 (dxJointPlane2D *joint, dxJoint::Info2 *info)
3961/***************************************************************************/
3962{
3963 int r0 = 0,
3964 r1 = info->rowskip,
3965 r2 = 2 * r1;
3966 dReal eps = info->fps * info->erp;
3967
3968 /* MINFO ("plane2dGetInfo2 ()"); */
3969
3970/*
3971 v = v1, w = omega1
3972 (v2, omega2 not important (== static environment))
3973
3974 constraint equations:
3975 xz = 0
3976 wx = 0
3977 wy = 0
3978
3979 <=> ( 0 0 1 ) (vx) ( 0 0 0 ) (wx) ( 0 )
3980 ( 0 0 0 ) (vy) + ( 1 0 0 ) (wy) = ( 0 )
3981 ( 0 0 0 ) (vz) ( 0 1 0 ) (wz) ( 0 )
3982 J1/J1l Omega1/J1a
3983*/
3984
3985 // fill in linear and angular coeff. for left hand side:
3986
3987 VoXYZ (&info->J1l[r0], =, 0, 0, 1);
3988 VoXYZ (&info->J1l[r1], =, 0, 0, 0);
3989 VoXYZ (&info->J1l[r2], =, 0, 0, 0);
3990
3991 VoXYZ (&info->J1a[r0], =, 0, 0, 0);
3992 VoXYZ (&info->J1a[r1], =, 1, 0, 0);
3993 VoXYZ (&info->J1a[r2], =, 0, 1, 0);
3994
3995 // error correction (against drift):
3996
3997 // a) linear vz, so that z (== pos[2]) == 0
3998 info->c[0] = eps * -joint->node[0].body->posr.pos[2];
3999
4000# if 0
4001 // b) angular correction? -> left to application !!!
4002 dReal *body_z_axis = &joint->node[0].body->R[8];
4003 info->c[1] = eps * +atan2 (body_z_axis[1], body_z_axis[2]); // wx error
4004 info->c[2] = eps * -atan2 (body_z_axis[0], body_z_axis[2]); // wy error
4005# endif
4006
4007 // if the slider is powered, or has joint limits, add in the extra row:
4008
4009 if (joint->row_motor_x > 0)
4010 joint->motor_x.addLimot (
4011 joint, info, joint->row_motor_x, Midentity[0], 0);
4012
4013 if (joint->row_motor_y > 0)
4014 joint->motor_y.addLimot (
4015 joint, info, joint->row_motor_y, Midentity[1], 0);
4016
4017 if (joint->row_motor_angle > 0)
4018 joint->motor_angle.addLimot (
4019 joint, info, joint->row_motor_angle, Midentity[2], 1);
4020}
4021
4022
4023
4024dxJoint::Vtable __dplane2d_vtable =
4025{
4026 sizeof (dxJointPlane2D),
4027 (dxJoint::init_fn*) plane2dInit,
4028 (dxJoint::getInfo1_fn*) plane2dGetInfo1,
4029 (dxJoint::getInfo2_fn*) plane2dGetInfo2,
4030 dJointTypePlane2D
4031};
4032
4033
4034void dJointSetPlane2DXParam (dxJoint *joint,
4035 int parameter, dReal value)
4036{
4037 dUASSERT (joint, "bad joint argument");
4038 dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
4039 dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
4040 joint2d->motor_x.set (parameter, value);
4041}
4042
4043
4044void dJointSetPlane2DYParam (dxJoint *joint,
4045 int parameter, dReal value)
4046{
4047 dUASSERT (joint, "bad joint argument");
4048 dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
4049 dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
4050 joint2d->motor_y.set (parameter, value);
4051}
4052
4053
4054
4055void dJointSetPlane2DAngleParam (dxJoint *joint,
4056 int parameter, dReal value)
4057{
4058 dUASSERT (joint, "bad joint argument");
4059 dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
4060 dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
4061 joint2d->motor_angle.set (parameter, value);
4062}
4063
4064
4065
diff --git a/libraries/ode-0.9/ode/src/joint.h b/libraries/ode-0.9/ode/src/joint.h
deleted file mode 100644
index 27c013e..0000000
--- a/libraries/ode-0.9/ode/src/joint.h
+++ /dev/null
@@ -1,346 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifndef _ODE_JOINT_H_
24#define _ODE_JOINT_H_
25
26
27#include "objects.h"
28#include <ode/contact.h>
29#include "obstack.h"
30
31
32// joint flags
33enum {
34 // if this flag is set, the joint was allocated in a joint group
35 dJOINT_INGROUP = 1,
36
37 // if this flag is set, the joint was attached with arguments (0,body).
38 // our convention is to treat all attaches as (body,0), i.e. so node[0].body
39 // is always nonzero, so this flag records the fact that the arguments were
40 // swapped.
41 dJOINT_REVERSE = 2,
42
43 // if this flag is set, the joint can not have just one body attached to it,
44 // it must have either zero or two bodies attached.
45 dJOINT_TWOBODIES = 4
46};
47
48
49// there are two of these nodes in the joint, one for each connection to a
50// body. these are node of a linked list kept by each body of it's connecting
51// joints. but note that the body pointer in each node points to the body that
52// makes use of the *other* node, not this node. this trick makes it a bit
53// easier to traverse the body/joint graph.
54
55struct dxJointNode {
56 dxJoint *joint; // pointer to enclosing dxJoint object
57 dxBody *body; // *other* body this joint is connected to
58 dxJointNode *next; // next node in body's list of connected joints
59};
60
61
62struct dxJoint : public dObject {
63 // naming convention: the "first" body this is connected to is node[0].body,
64 // and the "second" body is node[1].body. if this joint is only connected
65 // to one body then the second body is 0.
66
67 // info returned by getInfo1 function. the constraint dimension is m (<=6).
68 // i.e. that is the total number of rows in the jacobian. `nub' is the
69 // number of unbounded variables (which have lo,hi = -/+ infinity).
70
71 struct Info1 {
72 int m,nub;
73 };
74
75 // info returned by getInfo2 function
76
77 struct Info2 {
78 // integrator parameters: frames per second (1/stepsize), default error
79 // reduction parameter (0..1).
80 dReal fps,erp;
81
82 // for the first and second body, pointers to two (linear and angular)
83 // n*3 jacobian sub matrices, stored by rows. these matrices will have
84 // been initialized to 0 on entry. if the second body is zero then the
85 // J2xx pointers may be 0.
86 dReal *J1l,*J1a,*J2l,*J2a;
87
88 // elements to jump from one row to the next in J's
89 int rowskip;
90
91 // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
92 // "constraint force mixing" vector. c is set to zero on entry, cfm is
93 // set to a constant value (typically very small or zero) value on entry.
94 dReal *c,*cfm;
95
96 // lo and hi limits for variables (set to -/+ infinity on entry).
97 dReal *lo,*hi;
98
99 // findex vector for variables. see the LCP solver interface for a
100 // description of what this does. this is set to -1 on entry.
101 // note that the returned indexes are relative to the first index of
102 // the constraint.
103 int *findex;
104 };
105
106 // virtual function table: size of the joint structure, function pointers.
107 // we do it this way instead of using C++ virtual functions because
108 // sometimes we need to allocate joints ourself within a memory pool.
109
110 typedef void init_fn (dxJoint *joint);
111 typedef void getInfo1_fn (dxJoint *joint, Info1 *info);
112 typedef void getInfo2_fn (dxJoint *joint, Info2 *info);
113 struct Vtable {
114 int size;
115 init_fn *init;
116 getInfo1_fn *getInfo1;
117 getInfo2_fn *getInfo2;
118 int typenum; // a dJointTypeXXX type number
119 };
120
121 Vtable *vtable; // virtual function table
122 int flags; // dJOINT_xxx flags
123 dxJointNode node[2]; // connections to bodies. node[1].body can be 0
124 dJointFeedback *feedback; // optional feedback structure
125 dReal lambda[6]; // lambda generated by last step
126};
127
128
129// joint group. NOTE: any joints in the group that have their world destroyed
130// will have their world pointer set to 0.
131
132struct dxJointGroup : public dBase {
133 int num; // number of joints on the stack
134 dObStack stack; // a stack of (possibly differently sized) dxJoint
135}; // objects.
136
137
138// common limit and motor information for a single joint axis of movement
139struct dxJointLimitMotor {
140 dReal vel,fmax; // powered joint: velocity, max force
141 dReal lostop,histop; // joint limits, relative to initial position
142 dReal fudge_factor; // when powering away from joint limits
143 dReal normal_cfm; // cfm to use when not at a stop
144 dReal stop_erp,stop_cfm; // erp and cfm for when at joint limit
145 dReal bounce; // restitution factor
146 // variables used between getInfo1() and getInfo2()
147 int limit; // 0=free, 1=at lo limit, 2=at hi limit
148 dReal limit_err; // if at limit, amount over limit
149
150 void init (dxWorld *);
151 void set (int num, dReal value);
152 dReal get (int num);
153 int testRotationalLimit (dReal angle);
154 int addLimot (dxJoint *joint, dxJoint::Info2 *info, int row,
155 dVector3 ax1, int rotational);
156};
157
158
159// ball and socket
160
161struct dxJointBall : public dxJoint {
162 dVector3 anchor1; // anchor w.r.t first body
163 dVector3 anchor2; // anchor w.r.t second body
164 dReal erp; // error reduction
165 dReal cfm; // constraint force mix in
166 void set (int num, dReal value);
167 dReal get (int num);
168};
169extern struct dxJoint::Vtable __dball_vtable;
170
171
172// hinge
173
174struct dxJointHinge : public dxJoint {
175 dVector3 anchor1; // anchor w.r.t first body
176 dVector3 anchor2; // anchor w.r.t second body
177 dVector3 axis1; // axis w.r.t first body
178 dVector3 axis2; // axis w.r.t second body
179 dQuaternion qrel; // initial relative rotation body1 -> body2
180 dxJointLimitMotor limot; // limit and motor information
181};
182extern struct dxJoint::Vtable __dhinge_vtable;
183
184
185// universal
186
187struct dxJointUniversal : public dxJoint {
188 dVector3 anchor1; // anchor w.r.t first body
189 dVector3 anchor2; // anchor w.r.t second body
190 dVector3 axis1; // axis w.r.t first body
191 dVector3 axis2; // axis w.r.t second body
192 dQuaternion qrel1; // initial relative rotation body1 -> virtual cross piece
193 dQuaternion qrel2; // initial relative rotation virtual cross piece -> body2
194 dxJointLimitMotor limot1; // limit and motor information for axis1
195 dxJointLimitMotor limot2; // limit and motor information for axis2
196};
197extern struct dxJoint::Vtable __duniversal_vtable;
198
199
200/**
201 * The axisP must be perpendicular to axis2
202 * <PRE>
203 * +-------------+
204 * | x |
205 * +------------\+
206 * Prismatic articulation .. ..
207 * | .. ..
208 * \/ .. ..
209 * +--------------+ --| __.. .. anchor2
210 * | x | .....|.......(__) ..
211 * +--------------+ --| ^ <
212 * |----------------------->|
213 * Offset |--- Rotoide articulation
214 * </PRE>
215 */
216struct dxJointPR : public dxJoint {
217
218 dVector3 anchor2; ///< @brief Position of the rotoide articulation
219 ///< w.r.t second body.
220 ///< @note Position of body 2 in world frame +
221 ///< anchor2 in world frame give the position
222 ///< of the rotoide articulation
223 dVector3 axisR1; ///< axis of the rotoide articulation w.r.t first body.
224 ///< @note This is considered as axis1 from the parameter
225 ///< view.
226 dVector3 axisR2; ///< axis of the rotoide articulation w.r.t second body.
227 ///< @note This is considered also as axis1 from the
228 ///< parameter view
229 dVector3 axisP1; ///< axis for the prismatic articulation w.r.t first body.
230 ///< @note This is considered as axis2 in from the parameter
231 ///< view
232 dQuaternion qrel; ///< initial relative rotation body1 -> body2.
233 dVector3 offset; ///< @brief vector between the body1 and the rotoide
234 ///< articulation.
235 ///<
236 ///< Going from the first to the second in the frame
237 ///< of body1.
238 ///< That should be aligned with body1 center along axisP
239 ///< This is calculated whe the axis are set.
240 dxJointLimitMotor limotR; ///< limit and motor information for the rotoide articulation.
241 dxJointLimitMotor limotP; ///< limit and motor information for the prismatic articulation.
242};
243extern struct dxJoint::Vtable __dPR_vtable;
244
245
246
247// slider. if body2 is 0 then qrel is the absolute rotation of body1 and
248// offset is the position of body1 center along axis1.
249
250struct dxJointSlider : public dxJoint {
251 dVector3 axis1; // axis w.r.t first body
252 dQuaternion qrel; // initial relative rotation body1 -> body2
253 dVector3 offset; // point relative to body2 that should be
254 // aligned with body1 center along axis1
255 dxJointLimitMotor limot; // limit and motor information
256};
257extern struct dxJoint::Vtable __dslider_vtable;
258
259
260// contact
261
262struct dxJointContact : public dxJoint {
263 int the_m; // number of rows computed by getInfo1
264 dContact contact;
265};
266extern struct dxJoint::Vtable __dcontact_vtable;
267
268
269// hinge 2
270
271struct dxJointHinge2 : public dxJoint {
272 dVector3 anchor1; // anchor w.r.t first body
273 dVector3 anchor2; // anchor w.r.t second body
274 dVector3 axis1; // axis 1 w.r.t first body
275 dVector3 axis2; // axis 2 w.r.t second body
276 dReal c0,s0; // cos,sin of desired angle between axis 1,2
277 dVector3 v1,v2; // angle ref vectors embedded in first body
278 dxJointLimitMotor limot1; // limit+motor info for axis 1
279 dxJointLimitMotor limot2; // limit+motor info for axis 2
280 dReal susp_erp,susp_cfm; // suspension parameters (erp,cfm)
281};
282extern struct dxJoint::Vtable __dhinge2_vtable;
283
284
285// angular motor
286
287struct dxJointAMotor : public dxJoint {
288 int num; // number of axes (0..3)
289 int mode; // a dAMotorXXX constant
290 int rel[3]; // what the axes are relative to (global,b1,b2)
291 dVector3 axis[3]; // three axes
292 dxJointLimitMotor limot[3]; // limit+motor info for axes
293 dReal angle[3]; // user-supplied angles for axes
294 // these vectors are used for calculating euler angles
295 dVector3 reference1; // original axis[2], relative to body 1
296 dVector3 reference2; // original axis[0], relative to body 2
297};
298extern struct dxJoint::Vtable __damotor_vtable;
299
300
301struct dxJointLMotor : public dxJoint {
302 int num;
303 int rel[3];
304 dVector3 axis[3];
305 dxJointLimitMotor limot[3];
306};
307
308extern struct dxJoint::Vtable __dlmotor_vtable;
309
310
311// 2d joint, constrains to z == 0
312
313struct dxJointPlane2D : public dxJoint
314{
315 int row_motor_x;
316 int row_motor_y;
317 int row_motor_angle;
318 dxJointLimitMotor motor_x;
319 dxJointLimitMotor motor_y;
320 dxJointLimitMotor motor_angle;
321};
322
323extern struct dxJoint::Vtable __dplane2d_vtable;
324
325
326// fixed
327
328struct dxJointFixed : public dxJoint {
329 dQuaternion qrel; // initial relative rotation body1 -> body2
330 dVector3 offset; // relative offset between the bodies
331 dReal erp; // error reduction parameter
332 dReal cfm; // constraint force mix-in
333 void set (int num, dReal value);
334 dReal get (int num);
335};
336extern struct dxJoint::Vtable __dfixed_vtable;
337
338
339// null joint, for testing only
340
341struct dxJointNull : public dxJoint {
342};
343extern struct dxJoint::Vtable __dnull_vtable;
344
345
346#endif
diff --git a/libraries/ode-0.9/ode/src/lcp.cpp b/libraries/ode-0.9/ode/src/lcp.cpp
deleted file mode 100644
index d03d3e8..0000000
--- a/libraries/ode-0.9/ode/src/lcp.cpp
+++ /dev/null
@@ -1,2007 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25
26THE ALGORITHM
27-------------
28
29solve A*x = b+w, with x and w subject to certain LCP conditions.
30each x(i),w(i) must lie on one of the three line segments in the following
31diagram. each line segment corresponds to one index set :
32
33 w(i)
34 /|\ | :
35 | | :
36 | |i in N :
37 w>0 | |state[i]=0 :
38 | | :
39 | | : i in C
40 w=0 + +-----------------------+
41 | : |
42 | : |
43 w<0 | : |i in N
44 | : |state[i]=1
45 | : |
46 | : |
47 +-------|-----------|-----------|----------> x(i)
48 lo 0 hi
49
50the Dantzig algorithm proceeds as follows:
51 for i=1:n
52 * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or
53 negative towards the line. as this is done, the other (x(j),w(j))
54 for j<i are constrained to be on the line. if any (x,w) reaches the
55 end of a line segment then it is switched between index sets.
56 * i is added to the appropriate index set depending on what line segment
57 it hits.
58
59we restrict lo(i) <= 0 and hi(i) >= 0. this makes the algorithm a bit
60simpler, because the starting point for x(i),w(i) is always on the dotted
61line x=0 and x will only ever increase in one direction, so it can only hit
62two out of the three line segments.
63
64
65NOTES
66-----
67
68this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m".
69the implementation is split into an LCP problem object (dLCP) and an LCP
70driver function. most optimization occurs in the dLCP object.
71
72a naive implementation of the algorithm requires either a lot of data motion
73or a lot of permutation-array lookup, because we are constantly re-ordering
74rows and columns. to avoid this and make a more optimized algorithm, a
75non-trivial data structure is used to represent the matrix A (this is
76implemented in the fast version of the dLCP object).
77
78during execution of this algorithm, some indexes in A are clamped (set C),
79some are non-clamped (set N), and some are "don't care" (where x=0).
80A,x,b,w (and other problem vectors) are permuted such that the clamped
81indexes are first, the unclamped indexes are next, and the don't-care
82indexes are last. this permutation is recorded in the array `p'.
83initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped,
84the corresponding elements of p are swapped.
85
86because the C and N elements are grouped together in the rows of A, we can do
87lots of work with a fast dot product function. if A,x,etc were not permuted
88and we only had a permutation array, then those dot products would be much
89slower as we would have a permutation array lookup in some inner loops.
90
91A is accessed through an array of row pointers, so that element (i,j) of the
92permuted matrix is A[i][j]. this makes row swapping fast. for column swapping
93we still have to actually move the data.
94
95during execution of this algorithm we maintain an L*D*L' factorization of
96the clamped submatrix of A (call it `AC') which is the top left nC*nC
97submatrix of A. there are two ways we could arrange the rows/columns in AC.
98
99(1) AC is always permuted such that L*D*L' = AC. this causes a problem
100 when a row/column is removed from C, because then all the rows/columns of A
101 between the deleted index and the end of C need to be rotated downward.
102 this results in a lot of data motion and slows things down.
103(2) L*D*L' is actually a factorization of a *permutation* of AC (which is
104 itself a permutation of the underlying A). this is what we do - the
105 permutation is recorded in the vector C. call this permutation A[C,C].
106 when a row/column is removed from C, all we have to do is swap two
107 rows/columns and manipulate C.
108
109*/
110
111#include <ode/common.h>
112#include "lcp.h"
113#include <ode/matrix.h>
114#include <ode/misc.h>
115#include "mat.h" // for testing
116#include <ode/timer.h> // for testing
117
118//***************************************************************************
119// code generation parameters
120
121// LCP debugging (mosty for fast dLCP) - this slows things down a lot
122//#define DEBUG_LCP
123
124//#define dLCP_SLOW // use slow dLCP object
125#define dLCP_FAST // use fast dLCP object
126
127// option 1 : matrix row pointers (less data copying)
128#define ROWPTRS
129#define ATYPE dReal **
130#define AROW(i) (A[i])
131
132// option 2 : no matrix row pointers (slightly faster inner loops)
133//#define NOROWPTRS
134//#define ATYPE dReal *
135//#define AROW(i) (A+(i)*nskip)
136
137// use protected, non-stack memory allocation system
138
139#ifdef dUSE_MALLOC_FOR_ALLOCA
140extern unsigned int dMemoryFlag;
141
142#define ALLOCA(t,v,s) t* v = (t*) malloc(s)
143#define UNALLOCA(t) free(t)
144
145#else
146
147#define ALLOCA(t,v,s) t* v =(t*)dALLOCA16(s)
148#define UNALLOCA(t) /* nothing */
149
150#endif
151
152#define NUB_OPTIMIZATIONS
153
154//***************************************************************************
155
156// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
157// A is nskip. this only references and swaps the lower triangle.
158// if `do_fast_row_swaps' is nonzero and row pointers are being used, then
159// rows will be swapped by exchanging row pointers. otherwise the data will
160// be copied.
161
162static void swapRowsAndCols (ATYPE A, int n, int i1, int i2, int nskip,
163 int do_fast_row_swaps)
164{
165 int i;
166 dAASSERT (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
167 nskip >= n && i1 < i2);
168
169# ifdef ROWPTRS
170 for (i=i1+1; i<i2; i++) A[i1][i] = A[i][i1];
171 for (i=i1+1; i<i2; i++) A[i][i1] = A[i2][i];
172 A[i1][i2] = A[i1][i1];
173 A[i1][i1] = A[i2][i1];
174 A[i2][i1] = A[i2][i2];
175 // swap rows, by swapping row pointers
176 if (do_fast_row_swaps) {
177 dReal *tmpp;
178 tmpp = A[i1];
179 A[i1] = A[i2];
180 A[i2] = tmpp;
181 }
182 else {
183 ALLOCA (dReal,tmprow,n * sizeof(dReal));
184
185#ifdef dUSE_MALLOC_FOR_ALLOCA
186 if (tmprow == NULL) {
187 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
188 return;
189 }
190#endif
191
192 memcpy (tmprow,A[i1],n * sizeof(dReal));
193 memcpy (A[i1],A[i2],n * sizeof(dReal));
194 memcpy (A[i2],tmprow,n * sizeof(dReal));
195 UNALLOCA(tmprow);
196 }
197 // swap columns the hard way
198 for (i=i2+1; i<n; i++) {
199 dReal tmp = A[i][i1];
200 A[i][i1] = A[i][i2];
201 A[i][i2] = tmp;
202 }
203# else
204 dReal tmp;
205 ALLOCA (dReal,tmprow,n * sizeof(dReal));
206
207#ifdef dUSE_MALLOC_FOR_ALLOCA
208 if (tmprow == NULL) {
209 return;
210 }
211#endif
212
213 if (i1 > 0) {
214 memcpy (tmprow,A+i1*nskip,i1*sizeof(dReal));
215 memcpy (A+i1*nskip,A+i2*nskip,i1*sizeof(dReal));
216 memcpy (A+i2*nskip,tmprow,i1*sizeof(dReal));
217 }
218 for (i=i1+1; i<i2; i++) {
219 tmp = A[i2*nskip+i];
220 A[i2*nskip+i] = A[i*nskip+i1];
221 A[i*nskip+i1] = tmp;
222 }
223 tmp = A[i1*nskip+i1];
224 A[i1*nskip+i1] = A[i2*nskip+i2];
225 A[i2*nskip+i2] = tmp;
226 for (i=i2+1; i<n; i++) {
227 tmp = A[i*nskip+i1];
228 A[i*nskip+i1] = A[i*nskip+i2];
229 A[i*nskip+i2] = tmp;
230 }
231 UNALLOCA(tmprow);
232# endif
233
234}
235
236
237// swap two indexes in the n*n LCP problem. i1 must be <= i2.
238
239static void swapProblem (ATYPE A, dReal *x, dReal *b, dReal *w, dReal *lo,
240 dReal *hi, int *p, int *state, int *findex,
241 int n, int i1, int i2, int nskip,
242 int do_fast_row_swaps)
243{
244 dReal tmp;
245 int tmpi;
246 dIASSERT (n>0 && i1 >=0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n &&
247 i1 <= i2);
248 if (i1==i2) return;
249 swapRowsAndCols (A,n,i1,i2,nskip,do_fast_row_swaps);
250#ifdef dUSE_MALLOC_FOR_ALLOCA
251 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
252 return;
253#endif
254 tmp = x[i1];
255 x[i1] = x[i2];
256 x[i2] = tmp;
257 tmp = b[i1];
258 b[i1] = b[i2];
259 b[i2] = tmp;
260 tmp = w[i1];
261 w[i1] = w[i2];
262 w[i2] = tmp;
263 tmp = lo[i1];
264 lo[i1] = lo[i2];
265 lo[i2] = tmp;
266 tmp = hi[i1];
267 hi[i1] = hi[i2];
268 hi[i2] = tmp;
269 tmpi = p[i1];
270 p[i1] = p[i2];
271 p[i2] = tmpi;
272 tmpi = state[i1];
273 state[i1] = state[i2];
274 state[i2] = tmpi;
275 if (findex) {
276 tmpi = findex[i1];
277 findex[i1] = findex[i2];
278 findex[i2] = tmpi;
279 }
280}
281
282
283// for debugging - check that L,d is the factorization of A[C,C].
284// A[C,C] has size nC*nC and leading dimension nskip.
285// L has size nC*nC and leading dimension nskip.
286// d has size nC.
287
288#ifdef DEBUG_LCP
289
290static void checkFactorization (ATYPE A, dReal *_L, dReal *_d,
291 int nC, int *C, int nskip)
292{
293 int i,j;
294 if (nC==0) return;
295
296 // get A1=A, copy the lower triangle to the upper triangle, get A2=A[C,C]
297 dMatrix A1 (nC,nC);
298 for (i=0; i<nC; i++) {
299 for (j=0; j<=i; j++) A1(i,j) = A1(j,i) = AROW(i)[j];
300 }
301 dMatrix A2 = A1.select (nC,C,nC,C);
302
303 // printf ("A1=\n"); A1.print(); printf ("\n");
304 // printf ("A2=\n"); A2.print(); printf ("\n");
305
306 // compute A3 = L*D*L'
307 dMatrix L (nC,nC,_L,nskip,1);
308 dMatrix D (nC,nC);
309 for (i=0; i<nC; i++) D(i,i) = 1/_d[i];
310 L.clearUpperTriangle();
311 for (i=0; i<nC; i++) L(i,i) = 1;
312 dMatrix A3 = L * D * L.transpose();
313
314 // printf ("L=\n"); L.print(); printf ("\n");
315 // printf ("D=\n"); D.print(); printf ("\n");
316 // printf ("A3=\n"); A2.print(); printf ("\n");
317
318 // compare A2 and A3
319 dReal diff = A2.maxDifference (A3);
320 if (diff > 1e-8)
321 dDebug (0,"L*D*L' check, maximum difference = %.6e\n",diff);
322}
323
324#endif
325
326
327// for debugging
328
329#ifdef DEBUG_LCP
330
331static void checkPermutations (int i, int n, int nC, int nN, int *p, int *C)
332{
333 int j,k;
334 dIASSERT (nC>=0 && nN>=0 && (nC+nN)==i && i < n);
335 for (k=0; k<i; k++) dIASSERT (p[k] >= 0 && p[k] < i);
336 for (k=i; k<n; k++) dIASSERT (p[k] == k);
337 for (j=0; j<nC; j++) {
338 int C_is_bad = 1;
339 for (k=0; k<nC; k++) if (C[k]==j) C_is_bad = 0;
340 dIASSERT (C_is_bad==0);
341 }
342}
343
344#endif
345
346//***************************************************************************
347// dLCP manipulator object. this represents an n*n LCP problem.
348//
349// two index sets C and N are kept. each set holds a subset of
350// the variable indexes 0..n-1. an index can only be in one set.
351// initially both sets are empty.
352//
353// the index set C is special: solutions to A(C,C)\A(C,i) can be generated.
354
355#ifdef dLCP_SLOW
356
357// simple but slow implementation of dLCP, for testing the LCP drivers.
358
359#include "array.h"
360
361struct dLCP {
362 int n,nub,nskip;
363 dReal *Adata,*x,*b,*w,*lo,*hi; // LCP problem data
364 ATYPE A; // A rows
365 dArray<int> C,N; // index sets
366 int last_i_for_solve1; // last i value given to solve1
367
368 dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
369 dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
370 dReal *_Dell, dReal *_ell, dReal *_tmp,
371 int *_state, int *_findex, int *_p, int *_C, dReal **Arows);
372 // the constructor is given an initial problem description (A,x,b,w) and
373 // space for other working data (which the caller may allocate on the stack).
374 // some of this data is specific to the fast dLCP implementation.
375 // the matrices A and L have size n*n, vectors have size n*1.
376 // A represents a symmetric matrix but only the lower triangle is valid.
377 // `nub' is the number of unbounded indexes at the start. all the indexes
378 // 0..nub-1 will be put into C.
379
380 ~dLCP();
381
382 int getNub() { return nub; }
383 // return the value of `nub'. the constructor may want to change it,
384 // so the caller should find out its new value.
385
386 // transfer functions: transfer index i to the given set (C or N). indexes
387 // less than `nub' can never be given. A,x,b,w,etc may be permuted by these
388 // functions, the caller must be robust to this.
389
390 void transfer_i_to_C (int i);
391 // this assumes C and N span 1:i-1. this also assumes that solve1() has
392 // been recently called for the same i without any other transfer
393 // functions in between (thereby allowing some data reuse for the fast
394 // implementation).
395 void transfer_i_to_N (int i);
396 // this assumes C and N span 1:i-1.
397 void transfer_i_from_N_to_C (int i);
398 void transfer_i_from_C_to_N (int i);
399
400 int numC();
401 int numN();
402 // return the number of indexes in set C/N
403
404 int indexC (int i);
405 int indexN (int i);
406 // return index i in set C/N.
407
408 // accessor and arithmetic functions. Aij translates as A(i,j), etc.
409 // make sure that only the lower triangle of A is ever referenced.
410
411 dReal Aii (int i);
412 dReal AiC_times_qC (int i, dReal *q);
413 dReal AiN_times_qN (int i, dReal *q); // for all Nj
414 void pN_equals_ANC_times_qC (dReal *p, dReal *q); // for all Nj
415 void pN_plusequals_ANi (dReal *p, int i, int sign=1);
416 // for all Nj. sign = +1,-1. assumes i > maximum index in N.
417 void pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q);
418 void pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q); // for all Nj
419 void solve1 (dReal *a, int i, int dir=1, int only_transfer=0);
420 // get a(C) = - dir * A(C,C) \ A(C,i). dir must be +/- 1.
421 // the fast version of this function computes some data that is needed by
422 // transfer_i_to_C(). if only_transfer is nonzero then this function
423 // *only* computes that data, it does not set a(C).
424
425 void unpermute();
426 // call this at the end of the LCP function. if the x/w values have been
427 // permuted then this will unscramble them.
428};
429
430
431dLCP::dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
432 dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
433 dReal *_Dell, dReal *_ell, dReal *_tmp,
434 int *_state, int *_findex, int *_p, int *_C, dReal **Arows)
435{
436 dUASSERT (_findex==0,"slow dLCP object does not support findex array");
437
438 n = _n;
439 nub = _nub;
440 Adata = _Adata;
441 A = 0;
442 x = _x;
443 b = _b;
444 w = _w;
445 lo = _lo;
446 hi = _hi;
447 nskip = dPAD(n);
448 dSetZero (x,n);
449 last_i_for_solve1 = -1;
450
451 int i,j;
452 C.setSize (n);
453 N.setSize (n);
454 for (i=0; i<n; i++) {
455 C[i] = 0;
456 N[i] = 0;
457 }
458
459# ifdef ROWPTRS
460 // make matrix row pointers
461 A = Arows;
462 for (i=0; i<n; i++) A[i] = Adata + i*nskip;
463# else
464 A = Adata;
465# endif
466
467 // lets make A symmetric
468 for (i=0; i<n; i++) {
469 for (j=i+1; j<n; j++) AROW(i)[j] = AROW(j)[i];
470 }
471
472 // if nub>0, put all indexes 0..nub-1 into C and solve for x
473 if (nub > 0) {
474 for (i=0; i<nub; i++) memcpy (_L+i*nskip,AROW(i),(i+1)*sizeof(dReal));
475 dFactorLDLT (_L,_d,nub,nskip);
476 memcpy (x,b,nub*sizeof(dReal));
477 dSolveLDLT (_L,_d,x,nub,nskip);
478 dSetZero (_w,nub);
479 for (i=0; i<nub; i++) C[i] = 1;
480 }
481}
482
483
484dLCP::~dLCP()
485{
486}
487
488
489void dLCP::transfer_i_to_C (int i)
490{
491 if (i < nub) dDebug (0,"bad i");
492 if (C[i]) dDebug (0,"i already in C");
493 if (N[i]) dDebug (0,"i already in N");
494 for (int k=0; k<i; k++) {
495 if (!(C[k] ^ N[k])) dDebug (0,"assumptions for C and N violated");
496 }
497 for (int k=i; k<n; k++)
498 if (C[k] || N[k]) dDebug (0,"assumptions for C and N violated");
499 if (i != last_i_for_solve1) dDebug (0,"assumptions for i violated");
500 last_i_for_solve1 = -1;
501 C[i] = 1;
502}
503
504
505void dLCP::transfer_i_to_N (int i)
506{
507 if (i < nub) dDebug (0,"bad i");
508 if (C[i]) dDebug (0,"i already in C");
509 if (N[i]) dDebug (0,"i already in N");
510 for (int k=0; k<i; k++)
511 if (!C[k] && !N[k]) dDebug (0,"assumptions for C and N violated");
512 for (int k=i; k<n; k++)
513 if (C[k] || N[k]) dDebug (0,"assumptions for C and N violated");
514 last_i_for_solve1 = -1;
515 N[i] = 1;
516}
517
518
519void dLCP::transfer_i_from_N_to_C (int i)
520{
521 if (i < nub) dDebug (0,"bad i");
522 if (C[i]) dDebug (0,"i already in C");
523 if (!N[i]) dDebug (0,"i not in N");
524 last_i_for_solve1 = -1;
525 N[i] = 0;
526 C[i] = 1;
527}
528
529
530void dLCP::transfer_i_from_C_to_N (int i)
531{
532 if (i < nub) dDebug (0,"bad i");
533 if (N[i]) dDebug (0,"i already in N");
534 if (!C[i]) dDebug (0,"i not in C");
535 last_i_for_solve1 = -1;
536 C[i] = 0;
537 N[i] = 1;
538}
539
540
541int dLCP::numC()
542{
543 int i,count=0;
544 for (i=0; i<n; i++) if (C[i]) count++;
545 return count;
546}
547
548
549int dLCP::numN()
550{
551 int i,count=0;
552 for (i=0; i<n; i++) if (N[i]) count++;
553 return count;
554}
555
556
557int dLCP::indexC (int i)
558{
559 int k,count=0;
560 for (k=0; k<n; k++) {
561 if (C[k]) {
562 if (count==i) return k;
563 count++;
564 }
565 }
566 dDebug (0,"bad index C (%d)",i);
567 return 0;
568}
569
570
571int dLCP::indexN (int i)
572{
573 int k,count=0;
574 for (k=0; k<n; k++) {
575 if (N[k]) {
576 if (count==i) return k;
577 count++;
578 }
579 }
580 dDebug (0,"bad index into N");
581 return 0;
582}
583
584
585dReal dLCP::Aii (int i)
586{
587 return AROW(i)[i];
588}
589
590
591dReal dLCP::AiC_times_qC (int i, dReal *q)
592{
593 dReal sum = 0;
594 for (int k=0; k<n; k++) if (C[k]) sum += AROW(i)[k] * q[k];
595 return sum;
596}
597
598
599dReal dLCP::AiN_times_qN (int i, dReal *q)
600{
601 dReal sum = 0;
602 for (int k=0; k<n; k++) if (N[k]) sum += AROW(i)[k] * q[k];
603 return sum;
604}
605
606
607void dLCP::pN_equals_ANC_times_qC (dReal *p, dReal *q)
608{
609 dReal sum;
610 for (int ii=0; ii<n; ii++) if (N[ii]) {
611 sum = 0;
612 for (int jj=0; jj<n; jj++) if (C[jj]) sum += AROW(ii)[jj] * q[jj];
613 p[ii] = sum;
614 }
615}
616
617
618void dLCP::pN_plusequals_ANi (dReal *p, int i, int sign)
619{
620 int k;
621 for (k=0; k<n; k++) if (N[k] && k >= i) dDebug (0,"N assumption violated");
622 if (sign > 0) {
623 for (k=0; k<n; k++) if (N[k]) p[k] += AROW(i)[k];
624 }
625 else {
626 for (k=0; k<n; k++) if (N[k]) p[k] -= AROW(i)[k];
627 }
628}
629
630
631void dLCP::pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q)
632{
633 for (int k=0; k<n; k++) if (C[k]) p[k] += s*q[k];
634}
635
636
637void dLCP::pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q)
638{
639 for (int k=0; k<n; k++) if (N[k]) p[k] += s*q[k];
640}
641
642
643void dLCP::solve1 (dReal *a, int i, int dir, int only_transfer)
644{
645
646 ALLOCA (dReal,AA,n*nskip*sizeof(dReal));
647#ifdef dUSE_MALLOC_FOR_ALLOCA
648 if (AA == NULL) {
649 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
650 return;
651 }
652#endif
653 ALLOCA (dReal,dd,n*sizeof(dReal));
654#ifdef dUSE_MALLOC_FOR_ALLOCA
655 if (dd == NULL) {
656 UNALLOCA(AA);
657 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
658 return;
659 }
660#endif
661 ALLOCA (dReal,bb,n*sizeof(dReal));
662#ifdef dUSE_MALLOC_FOR_ALLOCA
663 if (bb == NULL) {
664 UNALLOCA(AA);
665 UNALLOCA(dd);
666 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
667 return;
668 }
669#endif
670
671 int ii,jj,AAi,AAj;
672
673 last_i_for_solve1 = i;
674 AAi = 0;
675 for (ii=0; ii<n; ii++) if (C[ii]) {
676 AAj = 0;
677 for (jj=0; jj<n; jj++) if (C[jj]) {
678 AA[AAi*nskip+AAj] = AROW(ii)[jj];
679 AAj++;
680 }
681 bb[AAi] = AROW(i)[ii];
682 AAi++;
683 }
684 if (AAi==0) {
685 UNALLOCA (AA);
686 UNALLOCA (dd);
687 UNALLOCA (bb);
688 return;
689 }
690
691 dFactorLDLT (AA,dd,AAi,nskip);
692 dSolveLDLT (AA,dd,bb,AAi,nskip);
693
694 AAi=0;
695 if (dir > 0) {
696 for (ii=0; ii<n; ii++) if (C[ii]) a[ii] = -bb[AAi++];
697 }
698 else {
699 for (ii=0; ii<n; ii++) if (C[ii]) a[ii] = bb[AAi++];
700 }
701
702 UNALLOCA (AA);
703 UNALLOCA (dd);
704 UNALLOCA (bb);
705}
706
707
708void dLCP::unpermute()
709{
710}
711
712#endif // dLCP_SLOW
713
714//***************************************************************************
715// fast implementation of dLCP. see the above definition of dLCP for
716// interface comments.
717//
718// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is
719// permuted as the other vectors/matrices are permuted.
720//
721// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have
722// contiguous indexes. the don't-care indexes follow N.
723//
724// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are
725// added or removed from the set C the factorization is updated.
726// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A.
727// the leading dimension of the matrix L is always `nskip'.
728//
729// at the start there may be other indexes that are unbounded but are not
730// included in `nub'. dLCP will permute the matrix so that absolutely all
731// unbounded vectors are at the start. thus there may be some initial
732// permutation.
733//
734// the algorithms here assume certain patterns, particularly with respect to
735// index transfer.
736
737#ifdef dLCP_FAST
738
739struct dLCP {
740 int n,nskip,nub;
741 ATYPE A; // A rows
742 dReal *Adata,*x,*b,*w,*lo,*hi; // permuted LCP problem data
743 dReal *L,*d; // L*D*L' factorization of set C
744 dReal *Dell,*ell,*tmp;
745 int *state,*findex,*p,*C;
746 int nC,nN; // size of each index set
747
748 dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
749 dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
750 dReal *_Dell, dReal *_ell, dReal *_tmp,
751 int *_state, int *_findex, int *_p, int *_C, dReal **Arows);
752 int getNub() { return nub; }
753 void transfer_i_to_C (int i);
754 void transfer_i_to_N (int i)
755 { nN++; } // because we can assume C and N span 1:i-1
756 void transfer_i_from_N_to_C (int i);
757 void transfer_i_from_C_to_N (int i);
758 int numC() { return nC; }
759 int numN() { return nN; }
760 int indexC (int i) { return i; }
761 int indexN (int i) { return i+nC; }
762 dReal Aii (int i) { return AROW(i)[i]; }
763 dReal AiC_times_qC (int i, dReal *q) { return dDot (AROW(i),q,nC); }
764 dReal AiN_times_qN (int i, dReal *q) { return dDot (AROW(i)+nC,q+nC,nN); }
765 void pN_equals_ANC_times_qC (dReal *p, dReal *q);
766 void pN_plusequals_ANi (dReal *p, int i, int sign=1);
767 void pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q)
768 { for (int i=0; i<nC; i++) p[i] += s*q[i]; }
769 void pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q)
770 { for (int i=0; i<nN; i++) p[i+nC] += s*q[i+nC]; }
771 void solve1 (dReal *a, int i, int dir=1, int only_transfer=0);
772 void unpermute();
773};
774
775
776dLCP::dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
777 dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
778 dReal *_Dell, dReal *_ell, dReal *_tmp,
779 int *_state, int *_findex, int *_p, int *_C, dReal **Arows)
780{
781 n = _n;
782 nub = _nub;
783 Adata = _Adata;
784 A = 0;
785 x = _x;
786 b = _b;
787 w = _w;
788 lo = _lo;
789 hi = _hi;
790 L = _L;
791 d = _d;
792 Dell = _Dell;
793 ell = _ell;
794 tmp = _tmp;
795 state = _state;
796 findex = _findex;
797 p = _p;
798 C = _C;
799 nskip = dPAD(n);
800 dSetZero (x,n);
801
802 int k;
803
804# ifdef ROWPTRS
805 // make matrix row pointers
806 A = Arows;
807 for (k=0; k<n; k++) A[k] = Adata + k*nskip;
808# else
809 A = Adata;
810# endif
811
812 nC = 0;
813 nN = 0;
814 for (k=0; k<n; k++) p[k]=k; // initially unpermuted
815
816 /*
817 // for testing, we can do some random swaps in the area i > nub
818 if (nub < n) {
819 for (k=0; k<100; k++) {
820 int i1,i2;
821 do {
822 i1 = dRandInt(n-nub)+nub;
823 i2 = dRandInt(n-nub)+nub;
824 }
825 while (i1 > i2);
826 //printf ("--> %d %d\n",i1,i2);
827 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,i1,i2,nskip,0);
828 }
829 }
830 */
831
832 // permute the problem so that *all* the unbounded variables are at the
833 // start, i.e. look for unbounded variables not included in `nub'. we can
834 // potentially push up `nub' this way and get a bigger initial factorization.
835 // note that when we swap rows/cols here we must not just swap row pointers,
836 // as the initial factorization relies on the data being all in one chunk.
837 // variables that have findex >= 0 are *not* considered to be unbounded even
838 // if lo=-inf and hi=inf - this is because these limits may change during the
839 // solution process.
840
841 for (k=nub; k<n; k++) {
842 if (findex && findex[k] >= 0) continue;
843 if (lo[k]==-dInfinity && hi[k]==dInfinity) {
844 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nub,k,nskip,0);
845 nub++;
846 }
847 }
848
849 // if there are unbounded variables at the start, factorize A up to that
850 // point and solve for x. this puts all indexes 0..nub-1 into C.
851 if (nub > 0) {
852 for (k=0; k<nub; k++) memcpy (L+k*nskip,AROW(k),(k+1)*sizeof(dReal));
853 dFactorLDLT (L,d,nub,nskip);
854 memcpy (x,b,nub*sizeof(dReal));
855 dSolveLDLT (L,d,x,nub,nskip);
856 dSetZero (w,nub);
857 for (k=0; k<nub; k++) C[k] = k;
858 nC = nub;
859 }
860
861 // permute the indexes > nub such that all findex variables are at the end
862 if (findex) {
863 int num_at_end = 0;
864 for (k=n-1; k >= nub; k--) {
865 if (findex[k] >= 0) {
866 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,k,n-1-num_at_end,nskip,1);
867 num_at_end++;
868 }
869 }
870 }
871
872 // print info about indexes
873 /*
874 for (k=0; k<n; k++) {
875 if (k<nub) printf ("C");
876 else if (lo[k]==-dInfinity && hi[k]==dInfinity) printf ("c");
877 else printf (".");
878 }
879 printf ("\n");
880 */
881}
882
883
884void dLCP::transfer_i_to_C (int i)
885{
886 int j;
887 if (nC > 0) {
888 // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
889 for (j=0; j<nC; j++) L[nC*nskip+j] = ell[j];
890 d[nC] = dRecip (AROW(i)[i] - dDot(ell,Dell,nC));
891 }
892 else {
893 d[0] = dRecip (AROW(i)[i]);
894 }
895 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nC,i,nskip,1);
896 C[nC] = nC;
897 nC++;
898
899# ifdef DEBUG_LCP
900 checkFactorization (A,L,d,nC,C,nskip);
901 if (i < (n-1)) checkPermutations (i+1,n,nC,nN,p,C);
902# endif
903}
904
905
906void dLCP::transfer_i_from_N_to_C (int i)
907{
908 int j;
909 if (nC > 0) {
910 dReal *aptr = AROW(i);
911# ifdef NUB_OPTIMIZATIONS
912 // if nub>0, initial part of aptr unpermuted
913 for (j=0; j<nub; j++) Dell[j] = aptr[j];
914 for (j=nub; j<nC; j++) Dell[j] = aptr[C[j]];
915# else
916 for (j=0; j<nC; j++) Dell[j] = aptr[C[j]];
917# endif
918 dSolveL1 (L,Dell,nC,nskip);
919 for (j=0; j<nC; j++) ell[j] = Dell[j] * d[j];
920 for (j=0; j<nC; j++) L[nC*nskip+j] = ell[j];
921 d[nC] = dRecip (AROW(i)[i] - dDot(ell,Dell,nC));
922 }
923 else {
924 d[0] = dRecip (AROW(i)[i]);
925 }
926 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nC,i,nskip,1);
927 C[nC] = nC;
928 nN--;
929 nC++;
930
931 // @@@ TO DO LATER
932 // if we just finish here then we'll go back and re-solve for
933 // delta_x. but actually we can be more efficient and incrementally
934 // update delta_x here. but if we do this, we wont have ell and Dell
935 // to use in updating the factorization later.
936
937# ifdef DEBUG_LCP
938 checkFactorization (A,L,d,nC,C,nskip);
939# endif
940}
941
942
943void dLCP::transfer_i_from_C_to_N (int i)
944{
945 // remove a row/column from the factorization, and adjust the
946 // indexes (black magic!)
947 int j,k;
948 for (j=0; j<nC; j++) if (C[j]==i) {
949 dLDLTRemove (A,C,L,d,n,nC,j,nskip);
950 for (k=0; k<nC; k++) if (C[k]==nC-1) {
951 C[k] = C[j];
952 if (j < (nC-1)) memmove (C+j,C+j+1,(nC-j-1)*sizeof(int));
953 break;
954 }
955 dIASSERT (k < nC);
956 break;
957 }
958 dIASSERT (j < nC);
959 swapProblem (A,x,b,w,lo,hi,p,state,findex,n,i,nC-1,nskip,1);
960 nC--;
961 nN++;
962
963# ifdef DEBUG_LCP
964 checkFactorization (A,L,d,nC,C,nskip);
965# endif
966}
967
968
969void dLCP::pN_equals_ANC_times_qC (dReal *p, dReal *q)
970{
971 // we could try to make this matrix-vector multiplication faster using
972 // outer product matrix tricks, e.g. with the dMultidotX() functions.
973 // but i tried it and it actually made things slower on random 100x100
974 // problems because of the overhead involved. so we'll stick with the
975 // simple method for now.
976 for (int i=0; i<nN; i++) p[i+nC] = dDot (AROW(i+nC),q,nC);
977}
978
979
980void dLCP::pN_plusequals_ANi (dReal *p, int i, int sign)
981{
982 dReal *aptr = AROW(i)+nC;
983 if (sign > 0) {
984 for (int i=0; i<nN; i++) p[i+nC] += aptr[i];
985 }
986 else {
987 for (int i=0; i<nN; i++) p[i+nC] -= aptr[i];
988 }
989}
990
991
992void dLCP::solve1 (dReal *a, int i, int dir, int only_transfer)
993{
994 // the `Dell' and `ell' that are computed here are saved. if index i is
995 // later added to the factorization then they can be reused.
996 //
997 // @@@ question: do we need to solve for entire delta_x??? yes, but
998 // only if an x goes below 0 during the step.
999
1000 int j;
1001 if (nC > 0) {
1002 dReal *aptr = AROW(i);
1003# ifdef NUB_OPTIMIZATIONS
1004 // if nub>0, initial part of aptr[] is guaranteed unpermuted
1005 for (j=0; j<nub; j++) Dell[j] = aptr[j];
1006 for (j=nub; j<nC; j++) Dell[j] = aptr[C[j]];
1007# else
1008 for (j=0; j<nC; j++) Dell[j] = aptr[C[j]];
1009# endif
1010 dSolveL1 (L,Dell,nC,nskip);
1011 for (j=0; j<nC; j++) ell[j] = Dell[j] * d[j];
1012
1013 if (!only_transfer) {
1014 for (j=0; j<nC; j++) tmp[j] = ell[j];
1015 dSolveL1T (L,tmp,nC,nskip);
1016 if (dir > 0) {
1017 for (j=0; j<nC; j++) a[C[j]] = -tmp[j];
1018 }
1019 else {
1020 for (j=0; j<nC; j++) a[C[j]] = tmp[j];
1021 }
1022 }
1023 }
1024}
1025
1026
1027void dLCP::unpermute()
1028{
1029 // now we have to un-permute x and w
1030 int j;
1031 ALLOCA (dReal,tmp,n*sizeof(dReal));
1032#ifdef dUSE_MALLOC_FOR_ALLOCA
1033 if (tmp == NULL) {
1034 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1035 return;
1036 }
1037#endif
1038 memcpy (tmp,x,n*sizeof(dReal));
1039 for (j=0; j<n; j++) x[p[j]] = tmp[j];
1040 memcpy (tmp,w,n*sizeof(dReal));
1041 for (j=0; j<n; j++) w[p[j]] = tmp[j];
1042
1043 UNALLOCA (tmp);
1044}
1045
1046#endif // dLCP_FAST
1047
1048//***************************************************************************
1049// an unoptimized Dantzig LCP driver routine for the basic LCP problem.
1050// must have lo=0, hi=dInfinity, and nub=0.
1051
1052void dSolveLCPBasic (int n, dReal *A, dReal *x, dReal *b,
1053 dReal *w, int nub, dReal *lo, dReal *hi)
1054{
1055 dAASSERT (n>0 && A && x && b && w && nub == 0);
1056
1057 int i,k;
1058 int nskip = dPAD(n);
1059 ALLOCA (dReal,L,n*nskip*sizeof(dReal));
1060#ifdef dUSE_MALLOC_FOR_ALLOCA
1061 if (L == NULL) {
1062 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1063 return;
1064 }
1065#endif
1066 ALLOCA (dReal,d,n*sizeof(dReal));
1067#ifdef dUSE_MALLOC_FOR_ALLOCA
1068 if (d == NULL) {
1069 UNALLOCA(L);
1070 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1071 return;
1072 }
1073#endif
1074 ALLOCA (dReal,delta_x,n*sizeof(dReal));
1075#ifdef dUSE_MALLOC_FOR_ALLOCA
1076 if (delta_x == NULL) {
1077 UNALLOCA(d);
1078 UNALLOCA(L);
1079 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1080 return;
1081 }
1082#endif
1083 ALLOCA (dReal,delta_w,n*sizeof(dReal));
1084#ifdef dUSE_MALLOC_FOR_ALLOCA
1085 if (delta_w == NULL) {
1086 UNALLOCA(delta_x);
1087 UNALLOCA(d);
1088 UNALLOCA(L);
1089 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1090 return;
1091 }
1092#endif
1093 ALLOCA (dReal,Dell,n*sizeof(dReal));
1094#ifdef dUSE_MALLOC_FOR_ALLOCA
1095 if (Dell == NULL) {
1096 UNALLOCA(delta_w);
1097 UNALLOCA(delta_x);
1098 UNALLOCA(d);
1099 UNALLOCA(L);
1100 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1101 return;
1102 }
1103#endif
1104 ALLOCA (dReal,ell,n*sizeof(dReal));
1105#ifdef dUSE_MALLOC_FOR_ALLOCA
1106 if (ell == NULL) {
1107 UNALLOCA(Dell);
1108 UNALLOCA(delta_w);
1109 UNALLOCA(delta_x);
1110 UNALLOCA(d);
1111 UNALLOCA(L);
1112 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1113 return;
1114 }
1115#endif
1116 ALLOCA (dReal,tmp,n*sizeof(dReal));
1117#ifdef dUSE_MALLOC_FOR_ALLOCA
1118 if (tmp == NULL) {
1119 UNALLOCA(ell);
1120 UNALLOCA(Dell);
1121 UNALLOCA(delta_w);
1122 UNALLOCA(delta_x);
1123 UNALLOCA(d);
1124 UNALLOCA(L);
1125 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1126 return;
1127 }
1128#endif
1129 ALLOCA (dReal*,Arows,n*sizeof(dReal*));
1130#ifdef dUSE_MALLOC_FOR_ALLOCA
1131 if (Arows == NULL) {
1132 UNALLOCA(tmp);
1133 UNALLOCA(ell);
1134 UNALLOCA(Dell);
1135 UNALLOCA(delta_w);
1136 UNALLOCA(delta_x);
1137 UNALLOCA(d);
1138 UNALLOCA(L);
1139 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1140 return;
1141 }
1142#endif
1143 ALLOCA (int,p,n*sizeof(int));
1144#ifdef dUSE_MALLOC_FOR_ALLOCA
1145 if (p == NULL) {
1146 UNALLOCA(Arows);
1147 UNALLOCA(tmp);
1148 UNALLOCA(ell);
1149 UNALLOCA(Dell);
1150 UNALLOCA(delta_w);
1151 UNALLOCA(delta_x);
1152 UNALLOCA(d);
1153 UNALLOCA(L);
1154 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1155 return;
1156 }
1157#endif
1158 ALLOCA (int,C,n*sizeof(int));
1159#ifdef dUSE_MALLOC_FOR_ALLOCA
1160 if (C == NULL) {
1161 UNALLOCA(p);
1162 UNALLOCA(Arows);
1163 UNALLOCA(tmp);
1164 UNALLOCA(ell);
1165 UNALLOCA(Dell);
1166 UNALLOCA(delta_w);
1167 UNALLOCA(delta_x);
1168 UNALLOCA(d);
1169 UNALLOCA(L);
1170 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1171 return;
1172 }
1173#endif
1174 ALLOCA (int,dummy,n*sizeof(int));
1175#ifdef dUSE_MALLOC_FOR_ALLOCA
1176 if (dummy == NULL) {
1177 UNALLOCA(C);
1178 UNALLOCA(p);
1179 UNALLOCA(Arows);
1180 UNALLOCA(tmp);
1181 UNALLOCA(ell);
1182 UNALLOCA(Dell);
1183 UNALLOCA(delta_w);
1184 UNALLOCA(delta_x);
1185 UNALLOCA(d);
1186 UNALLOCA(L);
1187 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1188 return;
1189 }
1190#endif
1191
1192
1193 dLCP lcp (n,0,A,x,b,w,tmp,tmp,L,d,Dell,ell,tmp,dummy,dummy,p,C,Arows);
1194 nub = lcp.getNub();
1195
1196 for (i=0; i<n; i++) {
1197 w[i] = lcp.AiC_times_qC (i,x) - b[i];
1198 if (w[i] >= 0) {
1199 lcp.transfer_i_to_N (i);
1200 }
1201 else {
1202 for (;;) {
1203 // compute: delta_x(C) = -A(C,C)\A(C,i)
1204 dSetZero (delta_x,n);
1205 lcp.solve1 (delta_x,i);
1206#ifdef dUSE_MALLOC_FOR_ALLOCA
1207 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1208 UNALLOCA(dummy);
1209 UNALLOCA(C);
1210 UNALLOCA(p);
1211 UNALLOCA(Arows);
1212 UNALLOCA(tmp);
1213 UNALLOCA(ell);
1214 UNALLOCA(Dell);
1215 UNALLOCA(delta_w);
1216 UNALLOCA(delta_x);
1217 UNALLOCA(d);
1218 UNALLOCA(L);
1219 return;
1220 }
1221#endif
1222 delta_x[i] = 1;
1223
1224 // compute: delta_w = A*delta_x
1225 dSetZero (delta_w,n);
1226 lcp.pN_equals_ANC_times_qC (delta_w,delta_x);
1227 lcp.pN_plusequals_ANi (delta_w,i);
1228 delta_w[i] = lcp.AiC_times_qC (i,delta_x) + lcp.Aii(i);
1229
1230 // find index to switch
1231 int si = i; // si = switch index
1232 int si_in_N = 0; // set to 1 if si in N
1233 dReal s = -w[i]/delta_w[i];
1234
1235 if (s <= 0) {
1236 dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
1237 if (i < (n-1)) {
1238 dSetZero (x+i,n-i);
1239 dSetZero (w+i,n-i);
1240 }
1241 goto done;
1242 }
1243
1244 for (k=0; k < lcp.numN(); k++) {
1245 if (delta_w[lcp.indexN(k)] < 0) {
1246 dReal s2 = -w[lcp.indexN(k)] / delta_w[lcp.indexN(k)];
1247 if (s2 < s) {
1248 s = s2;
1249 si = lcp.indexN(k);
1250 si_in_N = 1;
1251 }
1252 }
1253 }
1254 for (k=0; k < lcp.numC(); k++) {
1255 if (delta_x[lcp.indexC(k)] < 0) {
1256 dReal s2 = -x[lcp.indexC(k)] / delta_x[lcp.indexC(k)];
1257 if (s2 < s) {
1258 s = s2;
1259 si = lcp.indexC(k);
1260 si_in_N = 0;
1261 }
1262 }
1263 }
1264
1265 // apply x = x + s * delta_x
1266 lcp.pC_plusequals_s_times_qC (x,s,delta_x);
1267 x[i] += s;
1268 lcp.pN_plusequals_s_times_qN (w,s,delta_w);
1269 w[i] += s * delta_w[i];
1270
1271 // switch indexes between sets if necessary
1272 if (si==i) {
1273 w[i] = 0;
1274 lcp.transfer_i_to_C (i);
1275 break;
1276 }
1277 if (si_in_N) {
1278 w[si] = 0;
1279 lcp.transfer_i_from_N_to_C (si);
1280 }
1281 else {
1282 x[si] = 0;
1283 lcp.transfer_i_from_C_to_N (si);
1284 }
1285 }
1286 }
1287 }
1288
1289 done:
1290 lcp.unpermute();
1291
1292 UNALLOCA (L);
1293 UNALLOCA (d);
1294 UNALLOCA (delta_x);
1295 UNALLOCA (delta_w);
1296 UNALLOCA (Dell);
1297 UNALLOCA (ell);
1298 UNALLOCA (tmp);
1299 UNALLOCA (Arows);
1300 UNALLOCA (p);
1301 UNALLOCA (C);
1302 UNALLOCA (dummy);
1303}
1304
1305//***************************************************************************
1306// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
1307
1308void dSolveLCP (int n, dReal *A, dReal *x, dReal *b,
1309 dReal *w, int nub, dReal *lo, dReal *hi, int *findex)
1310{
1311 dAASSERT (n>0 && A && x && b && w && lo && hi && nub >= 0 && nub <= n);
1312
1313 int i,k,hit_first_friction_index = 0;
1314 int nskip = dPAD(n);
1315
1316 // if all the variables are unbounded then we can just factor, solve,
1317 // and return
1318 if (nub >= n) {
1319 dFactorLDLT (A,w,n,nskip); // use w for d
1320 dSolveLDLT (A,w,b,n,nskip);
1321 memcpy (x,b,n*sizeof(dReal));
1322 dSetZero (w,n);
1323
1324 return;
1325 }
1326# ifndef dNODEBUG
1327 // check restrictions on lo and hi
1328 for (k=0; k<n; k++) dIASSERT (lo[k] <= 0 && hi[k] >= 0);
1329# endif
1330 ALLOCA (dReal,L,n*nskip*sizeof(dReal));
1331#ifdef dUSE_MALLOC_FOR_ALLOCA
1332 if (L == NULL) {
1333 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1334 return;
1335 }
1336#endif
1337 ALLOCA (dReal,d,n*sizeof(dReal));
1338#ifdef dUSE_MALLOC_FOR_ALLOCA
1339 if (d == NULL) {
1340 UNALLOCA(L);
1341 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1342 return;
1343 }
1344#endif
1345 ALLOCA (dReal,delta_x,n*sizeof(dReal));
1346#ifdef dUSE_MALLOC_FOR_ALLOCA
1347 if (delta_x == NULL) {
1348 UNALLOCA(d);
1349 UNALLOCA(L);
1350 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1351 return;
1352 }
1353#endif
1354 ALLOCA (dReal,delta_w,n*sizeof(dReal));
1355#ifdef dUSE_MALLOC_FOR_ALLOCA
1356 if (delta_w == NULL) {
1357 UNALLOCA(delta_x);
1358 UNALLOCA(d);
1359 UNALLOCA(L);
1360 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1361 return;
1362 }
1363#endif
1364 ALLOCA (dReal,Dell,n*sizeof(dReal));
1365#ifdef dUSE_MALLOC_FOR_ALLOCA
1366 if (Dell == NULL) {
1367 UNALLOCA(delta_w);
1368 UNALLOCA(delta_x);
1369 UNALLOCA(d);
1370 UNALLOCA(L);
1371 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1372 return;
1373 }
1374#endif
1375 ALLOCA (dReal,ell,n*sizeof(dReal));
1376#ifdef dUSE_MALLOC_FOR_ALLOCA
1377 if (ell == NULL) {
1378 UNALLOCA(Dell);
1379 UNALLOCA(delta_w);
1380 UNALLOCA(delta_x);
1381 UNALLOCA(d);
1382 UNALLOCA(L);
1383 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1384 return;
1385 }
1386#endif
1387 ALLOCA (dReal*,Arows,n*sizeof(dReal*));
1388#ifdef dUSE_MALLOC_FOR_ALLOCA
1389 if (Arows == NULL) {
1390 UNALLOCA(ell);
1391 UNALLOCA(Dell);
1392 UNALLOCA(delta_w);
1393 UNALLOCA(delta_x);
1394 UNALLOCA(d);
1395 UNALLOCA(L);
1396 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1397 return;
1398 }
1399#endif
1400 ALLOCA (int,p,n*sizeof(int));
1401#ifdef dUSE_MALLOC_FOR_ALLOCA
1402 if (p == NULL) {
1403 UNALLOCA(Arows);
1404 UNALLOCA(ell);
1405 UNALLOCA(Dell);
1406 UNALLOCA(delta_w);
1407 UNALLOCA(delta_x);
1408 UNALLOCA(d);
1409 UNALLOCA(L);
1410 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1411 return;
1412 }
1413#endif
1414 ALLOCA (int,C,n*sizeof(int));
1415#ifdef dUSE_MALLOC_FOR_ALLOCA
1416 if (C == NULL) {
1417 UNALLOCA(p);
1418 UNALLOCA(Arows);
1419 UNALLOCA(ell);
1420 UNALLOCA(Dell);
1421 UNALLOCA(delta_w);
1422 UNALLOCA(delta_x);
1423 UNALLOCA(d);
1424 UNALLOCA(L);
1425 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1426 return;
1427 }
1428#endif
1429
1430 int dir;
1431 dReal dirf;
1432
1433 // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
1434 ALLOCA (int,state,n*sizeof(int));
1435#ifdef dUSE_MALLOC_FOR_ALLOCA
1436 if (state == NULL) {
1437 UNALLOCA(C);
1438 UNALLOCA(p);
1439 UNALLOCA(Arows);
1440 UNALLOCA(ell);
1441 UNALLOCA(Dell);
1442 UNALLOCA(delta_w);
1443 UNALLOCA(delta_x);
1444 UNALLOCA(d);
1445 UNALLOCA(L);
1446 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1447 return;
1448 }
1449#endif
1450
1451 // create LCP object. note that tmp is set to delta_w to save space, this
1452 // optimization relies on knowledge of how tmp is used, so be careful!
1453 dLCP *lcp=new dLCP(n,nub,A,x,b,w,lo,hi,L,d,Dell,ell,delta_w,state,findex,p,C,Arows);
1454 nub = lcp->getNub();
1455
1456 // loop over all indexes nub..n-1. for index i, if x(i),w(i) satisfy the
1457 // LCP conditions then i is added to the appropriate index set. otherwise
1458 // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
1459 // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
1460 // while driving x(i) we maintain the LCP conditions on the other variables
1461 // 0..i-1. we do this by watching out for other x(i),w(i) values going
1462 // outside the valid region, and then switching them between index sets
1463 // when that happens.
1464
1465 for (i=nub; i<n; i++) {
1466 // the index i is the driving index and indexes i+1..n-1 are "dont care",
1467 // i.e. when we make changes to the system those x's will be zero and we
1468 // don't care what happens to those w's. in other words, we only consider
1469 // an (i+1)*(i+1) sub-problem of A*x=b+w.
1470
1471 // if we've hit the first friction index, we have to compute the lo and
1472 // hi values based on the values of x already computed. we have been
1473 // permuting the indexes, so the values stored in the findex vector are
1474 // no longer valid. thus we have to temporarily unpermute the x vector.
1475 // for the purposes of this computation, 0*infinity = 0 ... so if the
1476 // contact constraint's normal force is 0, there should be no tangential
1477 // force applied.
1478
1479 if (hit_first_friction_index == 0 && findex && findex[i] >= 0) {
1480 // un-permute x into delta_w, which is not being used at the moment
1481 for (k=0; k<n; k++) delta_w[p[k]] = x[k];
1482
1483 // set lo and hi values
1484 for (k=i; k<n; k++) {
1485 dReal wfk = delta_w[findex[k]];
1486 if (wfk == 0) {
1487 hi[k] = 0;
1488 lo[k] = 0;
1489 }
1490 else {
1491 hi[k] = dFabs (hi[k] * wfk);
1492 lo[k] = -hi[k];
1493 }
1494 }
1495 hit_first_friction_index = 1;
1496 }
1497
1498 // thus far we have not even been computing the w values for indexes
1499 // greater than i, so compute w[i] now.
1500 w[i] = lcp->AiC_times_qC (i,x) + lcp->AiN_times_qN (i,x) - b[i];
1501
1502 // if lo=hi=0 (which can happen for tangential friction when normals are
1503 // 0) then the index will be assigned to set N with some state. however,
1504 // set C's line has zero size, so the index will always remain in set N.
1505 // with the "normal" switching logic, if w changed sign then the index
1506 // would have to switch to set C and then back to set N with an inverted
1507 // state. this is pointless, and also computationally expensive. to
1508 // prevent this from happening, we use the rule that indexes with lo=hi=0
1509 // will never be checked for set changes. this means that the state for
1510 // these indexes may be incorrect, but that doesn't matter.
1511
1512 // see if x(i),w(i) is in a valid region
1513 if (lo[i]==0 && w[i] >= 0) {
1514 lcp->transfer_i_to_N (i);
1515 state[i] = 0;
1516 }
1517 else if (hi[i]==0 && w[i] <= 0) {
1518 lcp->transfer_i_to_N (i);
1519 state[i] = 1;
1520 }
1521 else if (w[i]==0) {
1522 // this is a degenerate case. by the time we get to this test we know
1523 // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
1524 // and similarly that hi > 0. this means that the line segment
1525 // corresponding to set C is at least finite in extent, and we are on it.
1526 // NOTE: we must call lcp->solve1() before lcp->transfer_i_to_C()
1527 lcp->solve1 (delta_x,i,0,1);
1528
1529#ifdef dUSE_MALLOC_FOR_ALLOCA
1530 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1531 UNALLOCA(state);
1532 UNALLOCA(C);
1533 UNALLOCA(p);
1534 UNALLOCA(Arows);
1535 UNALLOCA(ell);
1536 UNALLOCA(Dell);
1537 UNALLOCA(delta_w);
1538 UNALLOCA(delta_x);
1539 UNALLOCA(d);
1540 UNALLOCA(L);
1541 return;
1542 }
1543#endif
1544
1545 lcp->transfer_i_to_C (i);
1546 }
1547 else {
1548 // we must push x(i) and w(i)
1549 for (;;) {
1550 // find direction to push on x(i)
1551 if (w[i] <= 0) {
1552 dir = 1;
1553 dirf = REAL(1.0);
1554 }
1555 else {
1556 dir = -1;
1557 dirf = REAL(-1.0);
1558 }
1559
1560 // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
1561 lcp->solve1 (delta_x,i,dir);
1562
1563#ifdef dUSE_MALLOC_FOR_ALLOCA
1564 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1565 UNALLOCA(state);
1566 UNALLOCA(C);
1567 UNALLOCA(p);
1568 UNALLOCA(Arows);
1569 UNALLOCA(ell);
1570 UNALLOCA(Dell);
1571 UNALLOCA(delta_w);
1572 UNALLOCA(delta_x);
1573 UNALLOCA(d);
1574 UNALLOCA(L);
1575 return;
1576 }
1577#endif
1578
1579 // note that delta_x[i] = dirf, but we wont bother to set it
1580
1581 // compute: delta_w = A*delta_x ... note we only care about
1582 // delta_w(N) and delta_w(i), the rest is ignored
1583 lcp->pN_equals_ANC_times_qC (delta_w,delta_x);
1584 lcp->pN_plusequals_ANi (delta_w,i,dir);
1585 delta_w[i] = lcp->AiC_times_qC (i,delta_x) + lcp->Aii(i)*dirf;
1586
1587 // find largest step we can take (size=s), either to drive x(i),w(i)
1588 // to the valid LCP region or to drive an already-valid variable
1589 // outside the valid region.
1590
1591 int cmd = 1; // index switching command
1592 int si = 0; // si = index to switch if cmd>3
1593 dReal s = -w[i]/delta_w[i];
1594 if (dir > 0) {
1595 if (hi[i] < dInfinity) {
1596 dReal s2 = (hi[i]-x[i])/dirf; // step to x(i)=hi(i)
1597 if (s2 < s) {
1598 s = s2;
1599 cmd = 3;
1600 }
1601 }
1602 }
1603 else {
1604 if (lo[i] > -dInfinity) {
1605 dReal s2 = (lo[i]-x[i])/dirf; // step to x(i)=lo(i)
1606 if (s2 < s) {
1607 s = s2;
1608 cmd = 2;
1609 }
1610 }
1611 }
1612
1613 for (k=0; k < lcp->numN(); k++) {
1614 if ((state[lcp->indexN(k)]==0 && delta_w[lcp->indexN(k)] < 0) ||
1615 (state[lcp->indexN(k)]!=0 && delta_w[lcp->indexN(k)] > 0)) {
1616 // don't bother checking if lo=hi=0
1617 if (lo[lcp->indexN(k)] == 0 && hi[lcp->indexN(k)] == 0) continue;
1618 dReal s2 = -w[lcp->indexN(k)] / delta_w[lcp->indexN(k)];
1619 if (s2 < s) {
1620 s = s2;
1621 cmd = 4;
1622 si = lcp->indexN(k);
1623 }
1624 }
1625 }
1626
1627 for (k=nub; k < lcp->numC(); k++) {
1628 if (delta_x[lcp->indexC(k)] < 0 && lo[lcp->indexC(k)] > -dInfinity) {
1629 dReal s2 = (lo[lcp->indexC(k)]-x[lcp->indexC(k)]) /
1630 delta_x[lcp->indexC(k)];
1631 if (s2 < s) {
1632 s = s2;
1633 cmd = 5;
1634 si = lcp->indexC(k);
1635 }
1636 }
1637 if (delta_x[lcp->indexC(k)] > 0 && hi[lcp->indexC(k)] < dInfinity) {
1638 dReal s2 = (hi[lcp->indexC(k)]-x[lcp->indexC(k)]) /
1639 delta_x[lcp->indexC(k)];
1640 if (s2 < s) {
1641 s = s2;
1642 cmd = 6;
1643 si = lcp->indexC(k);
1644 }
1645 }
1646 }
1647
1648 //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
1649 // "C->NL","C->NH"};
1650 //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);
1651
1652 // if s <= 0 then we've got a problem. if we just keep going then
1653 // we're going to get stuck in an infinite loop. instead, just cross
1654 // our fingers and exit with the current solution.
1655 if (s <= 0) {
1656 dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
1657 if (i < (n-1)) {
1658 dSetZero (x+i,n-i);
1659 dSetZero (w+i,n-i);
1660 }
1661 goto done;
1662 }
1663
1664 // apply x = x + s * delta_x
1665 lcp->pC_plusequals_s_times_qC (x,s,delta_x);
1666 x[i] += s * dirf;
1667
1668 // apply w = w + s * delta_w
1669 lcp->pN_plusequals_s_times_qN (w,s,delta_w);
1670 w[i] += s * delta_w[i];
1671
1672 // switch indexes between sets if necessary
1673 switch (cmd) {
1674 case 1: // done
1675 w[i] = 0;
1676 lcp->transfer_i_to_C (i);
1677 break;
1678 case 2: // done
1679 x[i] = lo[i];
1680 state[i] = 0;
1681 lcp->transfer_i_to_N (i);
1682 break;
1683 case 3: // done
1684 x[i] = hi[i];
1685 state[i] = 1;
1686 lcp->transfer_i_to_N (i);
1687 break;
1688 case 4: // keep going
1689 w[si] = 0;
1690 lcp->transfer_i_from_N_to_C (si);
1691 break;
1692 case 5: // keep going
1693 x[si] = lo[si];
1694 state[si] = 0;
1695 lcp->transfer_i_from_C_to_N (si);
1696 break;
1697 case 6: // keep going
1698 x[si] = hi[si];
1699 state[si] = 1;
1700 lcp->transfer_i_from_C_to_N (si);
1701 break;
1702 }
1703
1704 if (cmd <= 3) break;
1705 }
1706 }
1707 }
1708
1709 done:
1710 lcp->unpermute();
1711 delete lcp;
1712
1713 UNALLOCA (L);
1714 UNALLOCA (d);
1715 UNALLOCA (delta_x);
1716 UNALLOCA (delta_w);
1717 UNALLOCA (Dell);
1718 UNALLOCA (ell);
1719 UNALLOCA (Arows);
1720 UNALLOCA (p);
1721 UNALLOCA (C);
1722 UNALLOCA (state);
1723}
1724
1725//***************************************************************************
1726// accuracy and timing test
1727
1728extern "C" ODE_API void dTestSolveLCP()
1729{
1730 int n = 100;
1731 int i,nskip = dPAD(n);
1732#ifdef dDOUBLE
1733 const dReal tol = REAL(1e-9);
1734#endif
1735#ifdef dSINGLE
1736 const dReal tol = REAL(1e-4);
1737#endif
1738 printf ("dTestSolveLCP()\n");
1739
1740 ALLOCA (dReal,A,n*nskip*sizeof(dReal));
1741#ifdef dUSE_MALLOC_FOR_ALLOCA
1742 if (A == NULL) {
1743 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1744 return;
1745 }
1746#endif
1747 ALLOCA (dReal,x,n*sizeof(dReal));
1748#ifdef dUSE_MALLOC_FOR_ALLOCA
1749 if (x == NULL) {
1750 UNALLOCA (A);
1751 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1752 return;
1753 }
1754#endif
1755 ALLOCA (dReal,b,n*sizeof(dReal));
1756#ifdef dUSE_MALLOC_FOR_ALLOCA
1757 if (b == NULL) {
1758 UNALLOCA (x);
1759 UNALLOCA (A);
1760 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1761 return;
1762 }
1763#endif
1764 ALLOCA (dReal,w,n*sizeof(dReal));
1765#ifdef dUSE_MALLOC_FOR_ALLOCA
1766 if (w == NULL) {
1767 UNALLOCA (b);
1768 UNALLOCA (x);
1769 UNALLOCA (A);
1770 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1771 return;
1772 }
1773#endif
1774 ALLOCA (dReal,lo,n*sizeof(dReal));
1775#ifdef dUSE_MALLOC_FOR_ALLOCA
1776 if (lo == NULL) {
1777 UNALLOCA (w);
1778 UNALLOCA (b);
1779 UNALLOCA (x);
1780 UNALLOCA (A);
1781 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1782 return;
1783 }
1784#endif
1785 ALLOCA (dReal,hi,n*sizeof(dReal));
1786#ifdef dUSE_MALLOC_FOR_ALLOCA
1787 if (hi == NULL) {
1788 UNALLOCA (lo);
1789 UNALLOCA (w);
1790 UNALLOCA (b);
1791 UNALLOCA (x);
1792 UNALLOCA (A);
1793 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1794 return;
1795 }
1796#endif
1797
1798 ALLOCA (dReal,A2,n*nskip*sizeof(dReal));
1799#ifdef dUSE_MALLOC_FOR_ALLOCA
1800 if (A2 == NULL) {
1801 UNALLOCA (hi);
1802 UNALLOCA (lo);
1803 UNALLOCA (w);
1804 UNALLOCA (b);
1805 UNALLOCA (x);
1806 UNALLOCA (A);
1807 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1808 return;
1809 }
1810#endif
1811 ALLOCA (dReal,b2,n*sizeof(dReal));
1812#ifdef dUSE_MALLOC_FOR_ALLOCA
1813 if (b2 == NULL) {
1814 UNALLOCA (A2);
1815 UNALLOCA (hi);
1816 UNALLOCA (lo);
1817 UNALLOCA (w);
1818 UNALLOCA (b);
1819 UNALLOCA (x);
1820 UNALLOCA (A);
1821 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1822 return;
1823 }
1824#endif
1825 ALLOCA (dReal,lo2,n*sizeof(dReal));
1826#ifdef dUSE_MALLOC_FOR_ALLOCA
1827 if (lo2 == NULL) {
1828 UNALLOCA (b2);
1829 UNALLOCA (A2);
1830 UNALLOCA (hi);
1831 UNALLOCA (lo);
1832 UNALLOCA (w);
1833 UNALLOCA (b);
1834 UNALLOCA (x);
1835 UNALLOCA (A);
1836 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1837 return;
1838 }
1839#endif
1840 ALLOCA (dReal,hi2,n*sizeof(dReal));
1841#ifdef dUSE_MALLOC_FOR_ALLOCA
1842 if (hi2 == NULL) {
1843 UNALLOCA (lo2);
1844 UNALLOCA (b2);
1845 UNALLOCA (A2);
1846 UNALLOCA (hi);
1847 UNALLOCA (lo);
1848 UNALLOCA (w);
1849 UNALLOCA (b);
1850 UNALLOCA (x);
1851 UNALLOCA (A);
1852 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1853 return;
1854 }
1855#endif
1856 ALLOCA (dReal,tmp1,n*sizeof(dReal));
1857#ifdef dUSE_MALLOC_FOR_ALLOCA
1858 if (tmp1 == NULL) {
1859 UNALLOCA (hi2);
1860 UNALLOCA (lo2);
1861 UNALLOCA (b2);
1862 UNALLOCA (A2);
1863 UNALLOCA (hi);
1864 UNALLOCA (lo);
1865 UNALLOCA (w);
1866 UNALLOCA (b);
1867 UNALLOCA (x);
1868 UNALLOCA (A);
1869 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1870 return;
1871 }
1872#endif
1873 ALLOCA (dReal,tmp2,n*sizeof(dReal));
1874#ifdef dUSE_MALLOC_FOR_ALLOCA
1875 if (tmp2 == NULL) {
1876 UNALLOCA (tmp1);
1877 UNALLOCA (hi2);
1878 UNALLOCA (lo2);
1879 UNALLOCA (b2);
1880 UNALLOCA (A2);
1881 UNALLOCA (hi);
1882 UNALLOCA (lo);
1883 UNALLOCA (w);
1884 UNALLOCA (b);
1885 UNALLOCA (x);
1886 UNALLOCA (A);
1887 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1888 return;
1889 }
1890#endif
1891
1892 double total_time = 0;
1893 for (int count=0; count < 1000; count++) {
1894
1895 // form (A,b) = a random positive definite LCP problem
1896 dMakeRandomMatrix (A2,n,n,1.0);
1897 dMultiply2 (A,A2,A2,n,n,n);
1898 dMakeRandomMatrix (x,n,1,1.0);
1899 dMultiply0 (b,A,x,n,n,1);
1900 for (i=0; i<n; i++) b[i] += (dRandReal()*REAL(0.2))-REAL(0.1);
1901
1902 // choose `nub' in the range 0..n-1
1903 int nub = 50; //dRandInt (n);
1904
1905 // make limits
1906 for (i=0; i<nub; i++) lo[i] = -dInfinity;
1907 for (i=0; i<nub; i++) hi[i] = dInfinity;
1908 //for (i=nub; i<n; i++) lo[i] = 0;
1909 //for (i=nub; i<n; i++) hi[i] = dInfinity;
1910 //for (i=nub; i<n; i++) lo[i] = -dInfinity;
1911 //for (i=nub; i<n; i++) hi[i] = 0;
1912 for (i=nub; i<n; i++) lo[i] = -(dRandReal()*REAL(1.0))-REAL(0.01);
1913 for (i=nub; i<n; i++) hi[i] = (dRandReal()*REAL(1.0))+REAL(0.01);
1914
1915 // set a few limits to lo=hi=0
1916 /*
1917 for (i=0; i<10; i++) {
1918 int j = dRandInt (n-nub) + nub;
1919 lo[j] = 0;
1920 hi[j] = 0;
1921 }
1922 */
1923
1924 // solve the LCP. we must make copy of A,b,lo,hi (A2,b2,lo2,hi2) for
1925 // SolveLCP() to permute. also, we'll clear the upper triangle of A2 to
1926 // ensure that it doesn't get referenced (if it does, the answer will be
1927 // wrong).
1928
1929 memcpy (A2,A,n*nskip*sizeof(dReal));
1930 dClearUpperTriangle (A2,n);
1931 memcpy (b2,b,n*sizeof(dReal));
1932 memcpy (lo2,lo,n*sizeof(dReal));
1933 memcpy (hi2,hi,n*sizeof(dReal));
1934 dSetZero (x,n);
1935 dSetZero (w,n);
1936
1937 dStopwatch sw;
1938 dStopwatchReset (&sw);
1939 dStopwatchStart (&sw);
1940
1941 dSolveLCP (n,A2,x,b2,w,nub,lo2,hi2,0);
1942#ifdef dUSE_MALLOC_FOR_ALLOCA
1943 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1944 UNALLOCA (tmp2);
1945 UNALLOCA (tmp1);
1946 UNALLOCA (hi2);
1947 UNALLOCA (lo2);
1948 UNALLOCA (b2);
1949 UNALLOCA (A2);
1950 UNALLOCA (hi);
1951 UNALLOCA (lo);
1952 UNALLOCA (w);
1953 UNALLOCA (b);
1954 UNALLOCA (x);
1955 UNALLOCA (A);
1956 return;
1957 }
1958#endif
1959
1960 dStopwatchStop (&sw);
1961 double time = dStopwatchTime(&sw);
1962 total_time += time;
1963 double average = total_time / double(count+1) * 1000.0;
1964
1965 // check the solution
1966
1967 dMultiply0 (tmp1,A,x,n,n,1);
1968 for (i=0; i<n; i++) tmp2[i] = b[i] + w[i];
1969 dReal diff = dMaxDifference (tmp1,tmp2,n,1);
1970 // printf ("\tA*x = b+w, maximum difference = %.6e - %s (1)\n",diff,
1971 // diff > tol ? "FAILED" : "passed");
1972 if (diff > tol) dDebug (0,"A*x = b+w, maximum difference = %.6e",diff);
1973 int n1=0,n2=0,n3=0;
1974 for (i=0; i<n; i++) {
1975 if (x[i]==lo[i] && w[i] >= 0) {
1976 n1++; // ok
1977 }
1978 else if (x[i]==hi[i] && w[i] <= 0) {
1979 n2++; // ok
1980 }
1981 else if (x[i] >= lo[i] && x[i] <= hi[i] && w[i] == 0) {
1982 n3++; // ok
1983 }
1984 else {
1985 dDebug (0,"FAILED: i=%d x=%.4e w=%.4e lo=%.4e hi=%.4e",i,
1986 x[i],w[i],lo[i],hi[i]);
1987 }
1988 }
1989
1990 // pacifier
1991 printf ("passed: NL=%3d NH=%3d C=%3d ",n1,n2,n3);
1992 printf ("time=%10.3f ms avg=%10.4f\n",time * 1000.0,average);
1993 }
1994
1995 UNALLOCA (A);
1996 UNALLOCA (x);
1997 UNALLOCA (b);
1998 UNALLOCA (w);
1999 UNALLOCA (lo);
2000 UNALLOCA (hi);
2001 UNALLOCA (A2);
2002 UNALLOCA (b2);
2003 UNALLOCA (lo2);
2004 UNALLOCA (hi2);
2005 UNALLOCA (tmp1);
2006 UNALLOCA (tmp2);
2007}
diff --git a/libraries/ode-0.9/ode/src/lcp.h b/libraries/ode-0.9/ode/src/lcp.h
deleted file mode 100644
index 484902c..0000000
--- a/libraries/ode-0.9/ode/src/lcp.h
+++ /dev/null
@@ -1,58 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i)
26satisfies one of
27 (1) x = lo, w >= 0
28 (2) x = hi, w <= 0
29 (3) lo < x < hi, w = 0
30A is a matrix of dimension n*n, everything else is a vector of size n*1.
31lo and hi can be +/- dInfinity as needed. the first `nub' variables are
32unbounded, i.e. hi and lo are assumed to be +/- dInfinity.
33
34we restrict lo(i) <= 0 and hi(i) >= 0.
35
36the original data (A,b) may be modified by this function.
37
38if the `findex' (friction index) parameter is nonzero, it points to an array
39of index values. in this case constraints that have findex[i] >= 0 are
40special. all non-special constraints are solved for, then the lo and hi values
41for the special constraints are set:
42 hi[i] = abs( hi[i] * x[findex[i]] )
43 lo[i] = -hi[i]
44and the solution continues. this mechanism allows a friction approximation
45to be implemented. the first `nub' variables are assumed to have findex < 0.
46
47*/
48
49
50#ifndef _ODE_LCP_H_
51#define _ODE_LCP_H_
52
53
54void dSolveLCP (int n, dReal *A, dReal *x, dReal *b, dReal *w,
55 int nub, dReal *lo, dReal *hi, int *findex);
56
57
58#endif
diff --git a/libraries/ode-0.9/ode/src/mass.cpp b/libraries/ode-0.9/ode/src/mass.cpp
deleted file mode 100644
index 7d0b1c2..0000000
--- a/libraries/ode-0.9/ode/src/mass.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/mass.h>
25#include <ode/odemath.h>
26#include <ode/matrix.h>
27
28// Local dependencies
29#include "collision_kernel.h"
30
31#define SQR(x) ((x)*(x)) //!< Returns x square
32#define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
33
34#define _I(i,j) I[(i)*4+(j)]
35
36
37// return 1 if ok, 0 if bad
38
39int dMassCheck (const dMass *m)
40{
41 int i;
42
43 if (m->mass <= 0) {
44 dDEBUGMSG ("mass must be > 0");
45 return 0;
46 }
47 if (!dIsPositiveDefinite (m->I,3)) {
48 dDEBUGMSG ("inertia must be positive definite");
49 return 0;
50 }
51
52 // verify that the center of mass position is consistent with the mass
53 // and inertia matrix. this is done by checking that the inertia around
54 // the center of mass is also positive definite. from the comment in
55 // dMassTranslate(), if the body is translated so that its center of mass
56 // is at the point of reference, then the new inertia is:
57 // I + mass*crossmat(c)^2
58 // note that requiring this to be positive definite is exactly equivalent
59 // to requiring that the spatial inertia matrix
60 // [ mass*eye(3,3) M*crossmat(c)^T ]
61 // [ M*crossmat(c) I ]
62 // is positive definite, given that I is PD and mass>0. see the theorem
63 // about partitioned PD matrices for proof.
64
65 dMatrix3 I2,chat;
66 dSetZero (chat,12);
67 dCROSSMAT (chat,m->c,4,+,-);
68 dMULTIPLY0_333 (I2,chat,chat);
69 for (i=0; i<3; i++) I2[i] = m->I[i] + m->mass*I2[i];
70 for (i=4; i<7; i++) I2[i] = m->I[i] + m->mass*I2[i];
71 for (i=8; i<11; i++) I2[i] = m->I[i] + m->mass*I2[i];
72 if (!dIsPositiveDefinite (I2,3)) {
73 dDEBUGMSG ("center of mass inconsistent with mass parameters");
74 return 0;
75 }
76 return 1;
77}
78
79
80void dMassSetZero (dMass *m)
81{
82 dAASSERT (m);
83 m->mass = REAL(0.0);
84 dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
85 dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
86}
87
88
89void dMassSetParameters (dMass *m, dReal themass,
90 dReal cgx, dReal cgy, dReal cgz,
91 dReal I11, dReal I22, dReal I33,
92 dReal I12, dReal I13, dReal I23)
93{
94 dAASSERT (m);
95 dMassSetZero (m);
96 m->mass = themass;
97 m->c[0] = cgx;
98 m->c[1] = cgy;
99 m->c[2] = cgz;
100 m->_I(0,0) = I11;
101 m->_I(1,1) = I22;
102 m->_I(2,2) = I33;
103 m->_I(0,1) = I12;
104 m->_I(0,2) = I13;
105 m->_I(1,2) = I23;
106 m->_I(1,0) = I12;
107 m->_I(2,0) = I13;
108 m->_I(2,1) = I23;
109 dMassCheck (m);
110}
111
112
113void dMassSetSphere (dMass *m, dReal density, dReal radius)
114{
115 dMassSetSphereTotal (m, (REAL(4.0)/REAL(3.0)) * M_PI *
116 radius*radius*radius * density, radius);
117}
118
119
120void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius)
121{
122 dAASSERT (m);
123 dMassSetZero (m);
124 m->mass = total_mass;
125 dReal II = REAL(0.4) * total_mass * radius*radius;
126 m->_I(0,0) = II;
127 m->_I(1,1) = II;
128 m->_I(2,2) = II;
129
130# ifndef dNODEBUG
131 dMassCheck (m);
132# endif
133}
134
135
136void dMassSetCapsule (dMass *m, dReal density, int direction,
137 dReal radius, dReal length)
138{
139 dReal M1,M2,Ia,Ib;
140 dAASSERT (m);
141 dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
142 dMassSetZero (m);
143 M1 = M_PI*radius*radius*length*density; // cylinder mass
144 M2 = (REAL(4.0)/REAL(3.0))*M_PI*radius*radius*radius*density; // total cap mass
145 m->mass = M1+M2;
146 Ia = M1*(REAL(0.25)*radius*radius + (REAL(1.0)/REAL(12.0))*length*length) +
147 M2*(REAL(0.4)*radius*radius + REAL(0.375)*radius*length + REAL(0.25)*length*length);
148 Ib = (M1*REAL(0.5) + M2*REAL(0.4))*radius*radius;
149 m->_I(0,0) = Ia;
150 m->_I(1,1) = Ia;
151 m->_I(2,2) = Ia;
152 m->_I(direction-1,direction-1) = Ib;
153
154# ifndef dNODEBUG
155 dMassCheck (m);
156# endif
157}
158
159
160void dMassSetCapsuleTotal (dMass *m, dReal total_mass, int direction,
161 dReal a, dReal b)
162{
163 dMassSetCapsule (m, 1.0, direction, a, b);
164 dMassAdjust (m, total_mass);
165}
166
167
168void dMassSetCylinder (dMass *m, dReal density, int direction,
169 dReal radius, dReal length)
170{
171 dMassSetCylinderTotal (m, M_PI*radius*radius*length*density,
172 direction, radius, length);
173}
174
175void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction,
176 dReal radius, dReal length)
177{
178 dReal r2,I;
179 dAASSERT (m);
180 dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
181 dMassSetZero (m);
182 r2 = radius*radius;
183 m->mass = total_mass;
184 I = total_mass*(REAL(0.25)*r2 + (REAL(1.0)/REAL(12.0))*length*length);
185 m->_I(0,0) = I;
186 m->_I(1,1) = I;
187 m->_I(2,2) = I;
188 m->_I(direction-1,direction-1) = total_mass*REAL(0.5)*r2;
189
190# ifndef dNODEBUG
191 dMassCheck (m);
192# endif
193}
194
195
196void dMassSetBox (dMass *m, dReal density,
197 dReal lx, dReal ly, dReal lz)
198{
199 dMassSetBoxTotal (m, lx*ly*lz*density, lx, ly, lz);
200}
201
202
203void dMassSetBoxTotal (dMass *m, dReal total_mass,
204 dReal lx, dReal ly, dReal lz)
205{
206 dAASSERT (m);
207 dMassSetZero (m);
208 m->mass = total_mass;
209 m->_I(0,0) = total_mass/REAL(12.0) * (ly*ly + lz*lz);
210 m->_I(1,1) = total_mass/REAL(12.0) * (lx*lx + lz*lz);
211 m->_I(2,2) = total_mass/REAL(12.0) * (lx*lx + ly*ly);
212
213# ifndef dNODEBUG
214 dMassCheck (m);
215# endif
216}
217
218
219
220
221
222
223#if dTRIMESH_ENABLED
224
225/*
226 * dMassSetTrimesh, implementation by Gero Mueller.
227 * Based on Brian Mirtich, "Fast and Accurate Computation of
228 * Polyhedral Mass Properties," journal of graphics tools, volume 1,
229 * number 2, 1996.
230*/
231void dMassSetTrimesh( dMass *m, dReal density, dGeomID g )
232{
233 dAASSERT (m);
234 dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
235
236 dMassSetZero (m);
237
238 unsigned int triangles = dGeomTriMeshGetTriangleCount( g );
239
240 dReal nx, ny, nz;
241 unsigned int i, A, B, C;
242 // face integrals
243 dReal Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
244
245 // projection integrals
246 dReal P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
247
248 dReal T0 = 0;
249 dReal T1[3] = {0., 0., 0.};
250 dReal T2[3] = {0., 0., 0.};
251 dReal TP[3] = {0., 0., 0.};
252
253 for( i = 0; i < triangles; i++ )
254 {
255 dVector3 v0, v1, v2;
256 dGeomTriMeshGetTriangle( g, i, &v0, &v1, &v2);
257
258 dVector3 n, a, b;
259 dOP( a, -, v1, v0 );
260 dOP( b, -, v2, v0 );
261 dCROSS( n, =, b, a );
262 nx = fabs(n[0]);
263 ny = fabs(n[1]);
264 nz = fabs(n[2]);
265
266 if( nx > ny && nx > nz )
267 C = 0;
268 else
269 C = (ny > nz) ? 1 : 2;
270
271 A = (C + 1) % 3;
272 B = (A + 1) % 3;
273
274 // calculate face integrals
275 {
276 dReal w;
277 dReal k1, k2, k3, k4;
278
279 //compProjectionIntegrals(f);
280 {
281 dReal a0, a1, da;
282 dReal b0, b1, db;
283 dReal a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
284 dReal a1_2, a1_3, b1_2, b1_3;
285 dReal C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
286 dReal Cab, Kab, Caab, Kaab, Cabb, Kabb;
287
288 P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
289
290 for( int j = 0; j < 3; j++)
291 {
292 switch(j)
293 {
294 case 0:
295 a0 = v0[A];
296 b0 = v0[B];
297 a1 = v1[A];
298 b1 = v1[B];
299 break;
300 case 1:
301 a0 = v1[A];
302 b0 = v1[B];
303 a1 = v2[A];
304 b1 = v2[B];
305 break;
306 case 2:
307 a0 = v2[A];
308 b0 = v2[B];
309 a1 = v0[A];
310 b1 = v0[B];
311 break;
312 }
313 da = a1 - a0;
314 db = b1 - b0;
315 a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
316 b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
317 a1_2 = a1 * a1; a1_3 = a1_2 * a1;
318 b1_2 = b1 * b1; b1_3 = b1_2 * b1;
319
320 C1 = a1 + a0;
321 Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
322 Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
323 Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
324 Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
325 Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
326 Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
327
328 P1 += db*C1;
329 Pa += db*Ca;
330 Paa += db*Caa;
331 Paaa += db*Caaa;
332 Pb += da*Cb;
333 Pbb += da*Cbb;
334 Pbbb += da*Cbbb;
335 Pab += db*(b1*Cab + b0*Kab);
336 Paab += db*(b1*Caab + b0*Kaab);
337 Pabb += da*(a1*Cabb + a0*Kabb);
338 }
339
340 P1 /= 2.0;
341 Pa /= 6.0;
342 Paa /= 12.0;
343 Paaa /= 20.0;
344 Pb /= -6.0;
345 Pbb /= -12.0;
346 Pbbb /= -20.0;
347 Pab /= 24.0;
348 Paab /= 60.0;
349 Pabb /= -60.0;
350 }
351
352 w = - dDOT(n, v0);
353
354 k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1;
355
356 Fa = k1 * Pa;
357 Fb = k1 * Pb;
358 Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
359
360 Faa = k1 * Paa;
361 Fbb = k1 * Pbb;
362 Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb +
363 w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
364
365 Faaa = k1 * Paaa;
366 Fbbb = k1 * Pbbb;
367 Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab
368 + 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb
369 + 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb)
370 + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
371
372 Faab = k1 * Paab;
373 Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
374 Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb
375 + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
376 }
377
378
379 T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
380
381 T1[A] += n[A] * Faa;
382 T1[B] += n[B] * Fbb;
383 T1[C] += n[C] * Fcc;
384 T2[A] += n[A] * Faaa;
385 T2[B] += n[B] * Fbbb;
386 T2[C] += n[C] * Fccc;
387 TP[A] += n[A] * Faab;
388 TP[B] += n[B] * Fbbc;
389 TP[C] += n[C] * Fcca;
390 }
391
392 T1[0] /= 2; T1[1] /= 2; T1[2] /= 2;
393 T2[0] /= 3; T2[1] /= 3; T2[2] /= 3;
394 TP[0] /= 2; TP[1] /= 2; TP[2] /= 2;
395
396 m->mass = density * T0;
397 m->_I(0,0) = density * (T2[1] + T2[2]);
398 m->_I(1,1) = density * (T2[2] + T2[0]);
399 m->_I(2,2) = density * (T2[0] + T2[1]);
400 m->_I(0,1) = - density * TP[0];
401 m->_I(1,0) = - density * TP[0];
402 m->_I(2,1) = - density * TP[1];
403 m->_I(1,2) = - density * TP[1];
404 m->_I(2,0) = - density * TP[2];
405 m->_I(0,2) = - density * TP[2];
406
407 // Added to address SF bug 1729095
408 dMassTranslate( m, T1[0] / T0, T1[1] / T0, T1[2] / T0 );
409
410# ifndef dNODEBUG
411 dMassCheck (m);
412# endif
413}
414
415
416void dMassSetTrimeshTotal( dMass *m, dReal total_mass, dGeomID g)
417{
418 dAASSERT( m );
419 dUASSERT( g && g->type == dTriMeshClass, "argument not a trimesh" );
420 dMassSetTrimesh( m, 1.0, g );
421 dMassAdjust( m, total_mass );
422}
423
424#endif // dTRIMESH_ENABLED
425
426
427
428
429void dMassAdjust (dMass *m, dReal newmass)
430{
431 dAASSERT (m);
432 dReal scale = newmass / m->mass;
433 m->mass = newmass;
434 for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;
435
436# ifndef dNODEBUG
437 dMassCheck (m);
438# endif
439}
440
441
442void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
443{
444 // if the body is translated by `a' relative to its point of reference,
445 // the new inertia about the point of reference is:
446 //
447 // I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
448 //
449 // where c is the existing center of mass and I is the old inertia.
450
451 int i,j;
452 dMatrix3 ahat,chat,t1,t2;
453 dReal a[3];
454
455 dAASSERT (m);
456
457 // adjust inertia matrix
458 dSetZero (chat,12);
459 dCROSSMAT (chat,m->c,4,+,-);
460 a[0] = x + m->c[0];
461 a[1] = y + m->c[1];
462 a[2] = z + m->c[2];
463 dSetZero (ahat,12);
464 dCROSSMAT (ahat,a,4,+,-);
465 dMULTIPLY0_333 (t1,ahat,ahat);
466 dMULTIPLY0_333 (t2,chat,chat);
467 for (i=0; i<3; i++) for (j=0; j<3; j++)
468 m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);
469
470 // ensure perfect symmetry
471 m->_I(1,0) = m->_I(0,1);
472 m->_I(2,0) = m->_I(0,2);
473 m->_I(2,1) = m->_I(1,2);
474
475 // adjust center of mass
476 m->c[0] += x;
477 m->c[1] += y;
478 m->c[2] += z;
479
480# ifndef dNODEBUG
481 dMassCheck (m);
482# endif
483}
484
485
486void dMassRotate (dMass *m, const dMatrix3 R)
487{
488 // if the body is rotated by `R' relative to its point of reference,
489 // the new inertia about the point of reference is:
490 //
491 // R * I * R'
492 //
493 // where I is the old inertia.
494
495 dMatrix3 t1;
496 dReal t2[3];
497
498 dAASSERT (m);
499
500 // rotate inertia matrix
501 dMULTIPLY2_333 (t1,m->I,R);
502 dMULTIPLY0_333 (m->I,R,t1);
503
504 // ensure perfect symmetry
505 m->_I(1,0) = m->_I(0,1);
506 m->_I(2,0) = m->_I(0,2);
507 m->_I(2,1) = m->_I(1,2);
508
509 // rotate center of mass
510 dMULTIPLY0_331 (t2,R,m->c);
511 m->c[0] = t2[0];
512 m->c[1] = t2[1];
513 m->c[2] = t2[2];
514
515# ifndef dNODEBUG
516 dMassCheck (m);
517# endif
518}
519
520
521void dMassAdd (dMass *a, const dMass *b)
522{
523 int i;
524 dAASSERT (a && b);
525 dReal denom = dRecip (a->mass + b->mass);
526 for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
527 a->mass += b->mass;
528 for (i=0; i<12; i++) a->I[i] += b->I[i];
529}
diff --git a/libraries/ode-0.9/ode/src/mat.cpp b/libraries/ode-0.9/ode/src/mat.cpp
deleted file mode 100644
index 6e635dc..0000000
--- a/libraries/ode-0.9/ode/src/mat.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/misc.h>
25#include <ode/matrix.h>
26#include <ode/error.h>
27#include <ode/memory.h>
28#include "mat.h"
29
30
31dMatrix::dMatrix()
32{
33 n = 0;
34 m = 0;
35 data = 0;
36}
37
38
39dMatrix::dMatrix (int rows, int cols)
40{
41 if (rows < 1 || cols < 1) dDebug (0,"bad matrix size");
42 n = rows;
43 m = cols;
44 data = (dReal*) dAlloc (n*m*sizeof(dReal));
45 dSetZero (data,n*m);
46}
47
48
49dMatrix::dMatrix (const dMatrix &a)
50{
51 n = a.n;
52 m = a.m;
53 data = (dReal*) dAlloc (n*m*sizeof(dReal));
54 memcpy (data,a.data,n*m*sizeof(dReal));
55}
56
57
58dMatrix::dMatrix (int rows, int cols,
59 dReal *_data, int rowskip, int colskip)
60{
61 if (rows < 1 || cols < 1) dDebug (0,"bad matrix size");
62 n = rows;
63 m = cols;
64 data = (dReal*) dAlloc (n*m*sizeof(dReal));
65 for (int i=0; i<n; i++) {
66 for (int j=0; j<m; j++) data[i*m+j] = _data[i*rowskip + j*colskip];
67 }
68}
69
70
71dMatrix::~dMatrix()
72{
73 if (data) dFree (data,n*m*sizeof(dReal));
74}
75
76
77dReal & dMatrix::operator () (int i, int j)
78{
79 if (i < 0 || i >= n || j < 0 || j >= m) dDebug (0,"bad matrix (i,j)");
80 return data [i*m+j];
81}
82
83
84void dMatrix::operator= (const dMatrix &a)
85{
86 if (data) dFree (data,n*m*sizeof(dReal));
87 n = a.n;
88 m = a.m;
89 if (n > 0 && m > 0) {
90 data = (dReal*) dAlloc (n*m*sizeof(dReal));
91 memcpy (data,a.data,n*m*sizeof(dReal));
92 }
93 else data = 0;
94}
95
96
97void dMatrix::operator= (dReal a)
98{
99 for (int i=0; i<n*m; i++) data[i] = a;
100}
101
102
103dMatrix dMatrix::transpose()
104{
105 dMatrix r (m,n);
106 for (int i=0; i<n; i++) {
107 for (int j=0; j<m; j++) r.data[j*n+i] = data[i*m+j];
108 }
109 return r;
110}
111
112
113dMatrix dMatrix::select (int np, int *p, int nq, int *q)
114{
115 if (np < 1 || nq < 1) dDebug (0,"Matrix select, bad index array sizes");
116 dMatrix r (np,nq);
117 for (int i=0; i<np; i++) {
118 for (int j=0; j<nq; j++) {
119 if (p[i] < 0 || p[i] >= n || q[i] < 0 || q[i] >= m)
120 dDebug (0,"Matrix select, bad index arrays");
121 r.data[i*nq+j] = data[p[i]*m+q[j]];
122 }
123 }
124 return r;
125}
126
127
128dMatrix dMatrix::operator + (const dMatrix &a)
129{
130 if (n != a.n || m != a.m) dDebug (0,"matrix +, mismatched sizes");
131 dMatrix r (n,m);
132 for (int i=0; i<n*m; i++) r.data[i] = data[i] + a.data[i];
133 return r;
134}
135
136
137dMatrix dMatrix::operator - (const dMatrix &a)
138{
139 if (n != a.n || m != a.m) dDebug (0,"matrix -, mismatched sizes");
140 dMatrix r (n,m);
141 for (int i=0; i<n*m; i++) r.data[i] = data[i] - a.data[i];
142 return r;
143}
144
145
146dMatrix dMatrix::operator - ()
147{
148 dMatrix r (n,m);
149 for (int i=0; i<n*m; i++) r.data[i] = -data[i];
150 return r;
151}
152
153
154dMatrix dMatrix::operator * (const dMatrix &a)
155{
156 if (m != a.n) dDebug (0,"matrix *, mismatched sizes");
157 dMatrix r (n,a.m);
158 for (int i=0; i<n; i++) {
159 for (int j=0; j<a.m; j++) {
160 dReal sum = 0;
161 for (int k=0; k<m; k++) sum += data[i*m+k] * a.data[k*a.m+j];
162 r.data [i*a.m+j] = sum;
163 }
164 }
165 return r;
166}
167
168
169void dMatrix::operator += (const dMatrix &a)
170{
171 if (n != a.n || m != a.m) dDebug (0,"matrix +=, mismatched sizes");
172 for (int i=0; i<n*m; i++) data[i] += a.data[i];
173}
174
175
176void dMatrix::operator -= (const dMatrix &a)
177{
178 if (n != a.n || m != a.m) dDebug (0,"matrix -=, mismatched sizes");
179 for (int i=0; i<n*m; i++) data[i] -= a.data[i];
180}
181
182
183void dMatrix::clearUpperTriangle()
184{
185 if (n != m) dDebug (0,"clearUpperTriangle() only works on square matrices");
186 for (int i=0; i<n; i++) {
187 for (int j=i+1; j<m; j++) data[i*m+j] = 0;
188 }
189}
190
191
192void dMatrix::clearLowerTriangle()
193{
194 if (n != m) dDebug (0,"clearLowerTriangle() only works on square matrices");
195 for (int i=0; i<n; i++) {
196 for (int j=0; j<i; j++) data[i*m+j] = 0;
197 }
198}
199
200
201void dMatrix::makeRandom (dReal range)
202{
203 for (int i=0; i<n; i++) {
204 for (int j=0; j<m; j++)
205 data[i*m+j] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
206 }
207}
208
209
210void dMatrix::print (char *fmt, FILE *f)
211{
212 for (int i=0; i<n; i++) {
213 for (int j=0; j<m; j++) fprintf (f,fmt,data[i*m+j]);
214 fprintf (f,"\n");
215 }
216}
217
218
219dReal dMatrix::maxDifference (const dMatrix &a)
220{
221 if (n != a.n || m != a.m) dDebug (0,"maxDifference(), mismatched sizes");
222 dReal max = 0;
223 for (int i=0; i<n; i++) {
224 for (int j=0; j<m; j++) {
225 dReal diff = dFabs(data[i*m+j] - a.data[i*m+j]);
226 if (diff > max) max = diff;
227 }
228 }
229 return max;
230}
diff --git a/libraries/ode-0.9/ode/src/mat.h b/libraries/ode-0.9/ode/src/mat.h
deleted file mode 100644
index 2814a01..0000000
--- a/libraries/ode-0.9/ode/src/mat.h
+++ /dev/null
@@ -1,71 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// matrix class. this is mostly for convenience in the testing code, it is
24// not optimized at all. correctness is much more importance here.
25
26#ifndef _ODE_MAT_H_
27#define _ODE_MAT_H_
28
29#include <ode/common.h>
30
31
32class dMatrix {
33 int n,m; // matrix dimension, n,m >= 0
34 dReal *data; // if nonzero, n*m elements allocated on the heap
35
36public:
37 // constructors, destructors
38 dMatrix(); // make default 0x0 matrix
39 dMatrix (int rows, int cols); // construct zero matrix of given size
40 dMatrix (const dMatrix &); // construct copy of given matrix
41 // create copy of given data - element (i,j) is data[i*rowskip+j*colskip]
42 dMatrix (int rows, int cols, dReal *_data, int rowskip, int colskip);
43 ~dMatrix(); // destructor
44
45 // data movement
46 dReal & operator () (int i, int j); // reference an element
47 void operator= (const dMatrix &); // matrix = matrix
48 void operator= (dReal); // matrix = scalar
49 dMatrix transpose(); // return transposed matrix
50 // return a permuted submatrix of this matrix, made up of the rows in p
51 // and the columns in q. p has np elements, q has nq elements.
52 dMatrix select (int np, int *p, int nq, int *q);
53
54 // operators
55 dMatrix operator + (const dMatrix &);
56 dMatrix operator - (const dMatrix &);
57 dMatrix operator - ();
58 dMatrix operator * (const dMatrix &);
59 void operator += (const dMatrix &);
60 void operator -= (const dMatrix &);
61
62 // utility
63 void clearUpperTriangle();
64 void clearLowerTriangle();
65 void makeRandom (dReal range);
66 void print (char *fmt = "%10.4f ", FILE *f=stdout);
67 dReal maxDifference (const dMatrix &);
68};
69
70
71#endif
diff --git a/libraries/ode-0.9/ode/src/matrix.cpp b/libraries/ode-0.9/ode/src/matrix.cpp
deleted file mode 100644
index 16afe91..0000000
--- a/libraries/ode-0.9/ode/src/matrix.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/common.h>
24#include <ode/matrix.h>
25
26// misc defines
27#define ALLOCA dALLOCA16
28
29
30void dSetZero (dReal *a, int n)
31{
32 dAASSERT (a && n >= 0);
33 while (n > 0) {
34 *(a++) = 0;
35 n--;
36 }
37}
38
39
40void dSetValue (dReal *a, int n, dReal value)
41{
42 dAASSERT (a && n >= 0);
43 while (n > 0) {
44 *(a++) = value;
45 n--;
46 }
47}
48
49
50void dMultiply0 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
51{
52 int i,j,k,qskip,rskip,rpad;
53 dAASSERT (A && B && C && p>0 && q>0 && r>0);
54 qskip = dPAD(q);
55 rskip = dPAD(r);
56 rpad = rskip - r;
57 dReal sum;
58 const dReal *b,*c,*bb;
59 bb = B;
60 for (i=p; i; i--) {
61 for (j=0 ; j<r; j++) {
62 c = C + j;
63 b = bb;
64 sum = 0;
65 for (k=q; k; k--, c+=rskip) sum += (*(b++))*(*c);
66 *(A++) = sum;
67 }
68 A += rpad;
69 bb += qskip;
70 }
71}
72
73
74void dMultiply1 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
75{
76 int i,j,k,pskip,rskip;
77 dReal sum;
78 dAASSERT (A && B && C && p>0 && q>0 && r>0);
79 pskip = dPAD(p);
80 rskip = dPAD(r);
81 for (i=0; i<p; i++) {
82 for (j=0; j<r; j++) {
83 sum = 0;
84 for (k=0; k<q; k++) sum += B[i+k*pskip] * C[j+k*rskip];
85 A[i*rskip+j] = sum;
86 }
87 }
88}
89
90
91void dMultiply2 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
92{
93 int i,j,k,z,rpad,qskip;
94 dReal sum;
95 const dReal *bb,*cc;
96 dAASSERT (A && B && C && p>0 && q>0 && r>0);
97 rpad = dPAD(r) - r;
98 qskip = dPAD(q);
99 bb = B;
100 for (i=p; i; i--) {
101 cc = C;
102 for (j=r; j; j--) {
103 z = 0;
104 sum = 0;
105 for (k=q; k; k--,z++) sum += bb[z] * cc[z];
106 *(A++) = sum;
107 cc += qskip;
108 }
109 A += rpad;
110 bb += qskip;
111 }
112}
113
114
115int dFactorCholesky (dReal *A, int n)
116{
117 int i,j,k,nskip;
118 dReal sum,*a,*b,*aa,*bb,*cc,*recip;
119 dAASSERT (n > 0 && A);
120 nskip = dPAD (n);
121 recip = (dReal*) ALLOCA (n * sizeof(dReal));
122 aa = A;
123 for (i=0; i<n; i++) {
124 bb = A;
125 cc = A + i*nskip;
126 for (j=0; j<i; j++) {
127 sum = *cc;
128 a = aa;
129 b = bb;
130 for (k=j; k; k--) sum -= (*(a++))*(*(b++));
131 *cc = sum * recip[j];
132 bb += nskip;
133 cc++;
134 }
135 sum = *cc;
136 a = aa;
137 for (k=i; k; k--, a++) sum -= (*a)*(*a);
138 if (sum <= REAL(0.0)) return 0;
139 *cc = dSqrt(sum);
140 recip[i] = dRecip (*cc);
141 aa += nskip;
142 }
143 return 1;
144}
145
146
147void dSolveCholesky (const dReal *L, dReal *b, int n)
148{
149 int i,k,nskip;
150 dReal sum,*y;
151 dAASSERT (n > 0 && L && b);
152 nskip = dPAD (n);
153 y = (dReal*) ALLOCA (n*sizeof(dReal));
154 for (i=0; i<n; i++) {
155 sum = 0;
156 for (k=0; k < i; k++) sum += L[i*nskip+k]*y[k];
157 y[i] = (b[i]-sum)/L[i*nskip+i];
158 }
159 for (i=n-1; i >= 0; i--) {
160 sum = 0;
161 for (k=i+1; k < n; k++) sum += L[k*nskip+i]*b[k];
162 b[i] = (y[i]-sum)/L[i*nskip+i];
163 }
164}
165
166
167int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n)
168{
169 int i,j,nskip;
170 dReal *L,*x;
171 dAASSERT (n > 0 && A && Ainv);
172 nskip = dPAD (n);
173 L = (dReal*) ALLOCA (nskip*n*sizeof(dReal));
174 memcpy (L,A,nskip*n*sizeof(dReal));
175 x = (dReal*) ALLOCA (n*sizeof(dReal));
176 if (dFactorCholesky (L,n)==0) return 0;
177 dSetZero (Ainv,n*nskip); // make sure all padding elements set to 0
178 for (i=0; i<n; i++) {
179 for (j=0; j<n; j++) x[j] = 0;
180 x[i] = 1;
181 dSolveCholesky (L,x,n);
182 for (j=0; j<n; j++) Ainv[j*nskip+i] = x[j];
183 }
184 return 1;
185}
186
187
188int dIsPositiveDefinite (const dReal *A, int n)
189{
190 dReal *Acopy;
191 dAASSERT (n > 0 && A);
192 int nskip = dPAD (n);
193 Acopy = (dReal*) ALLOCA (nskip*n * sizeof(dReal));
194 memcpy (Acopy,A,nskip*n * sizeof(dReal));
195 return dFactorCholesky (Acopy,n);
196}
197
198
199/***** this has been replaced by a faster version
200void dSolveL1T (const dReal *L, dReal *b, int n, int nskip)
201{
202 int i,j;
203 dAASSERT (L && b && n >= 0 && nskip >= n);
204 dReal sum;
205 for (i=n-2; i>=0; i--) {
206 sum = 0;
207 for (j=i+1; j<n; j++) sum += L[j*nskip+i]*b[j];
208 b[i] -= sum;
209 }
210}
211*/
212
213
214void dVectorScale (dReal *a, const dReal *d, int n)
215{
216 dAASSERT (a && d && n >= 0);
217 for (int i=0; i<n; i++) a[i] *= d[i];
218}
219
220
221void dSolveLDLT (const dReal *L, const dReal *d, dReal *b, int n, int nskip)
222{
223 dAASSERT (L && d && b && n > 0 && nskip >= n);
224 dSolveL1 (L,b,n,nskip);
225 dVectorScale (b,d,n);
226 dSolveL1T (L,b,n,nskip);
227}
228
229
230void dLDLTAddTL (dReal *L, dReal *d, const dReal *a, int n, int nskip)
231{
232 int j,p;
233 dReal *W1,*W2,W11,W21,alpha1,alpha2,alphanew,gamma1,gamma2,k1,k2,Wp,ell,dee;
234 dAASSERT (L && d && a && n > 0 && nskip >= n);
235
236 if (n < 2) return;
237 W1 = (dReal*) ALLOCA (n*sizeof(dReal));
238 W2 = (dReal*) ALLOCA (n*sizeof(dReal));
239
240 W1[0] = 0;
241 W2[0] = 0;
242 for (j=1; j<n; j++) W1[j] = W2[j] = a[j] * M_SQRT1_2;
243 W11 = (REAL(0.5)*a[0]+1)*M_SQRT1_2;
244 W21 = (REAL(0.5)*a[0]-1)*M_SQRT1_2;
245
246 alpha1=1;
247 alpha2=1;
248
249 dee = d[0];
250 alphanew = alpha1 + (W11*W11)*dee;
251 dee /= alphanew;
252 gamma1 = W11 * dee;
253 dee *= alpha1;
254 alpha1 = alphanew;
255 alphanew = alpha2 - (W21*W21)*dee;
256 dee /= alphanew;
257 gamma2 = W21 * dee;
258 alpha2 = alphanew;
259 k1 = REAL(1.0) - W21*gamma1;
260 k2 = W21*gamma1*W11 - W21;
261 for (p=1; p<n; p++) {
262 Wp = W1[p];
263 ell = L[p*nskip];
264 W1[p] = Wp - W11*ell;
265 W2[p] = k1*Wp + k2*ell;
266 }
267
268 for (j=1; j<n; j++) {
269 dee = d[j];
270 alphanew = alpha1 + (W1[j]*W1[j])*dee;
271 dee /= alphanew;
272 gamma1 = W1[j] * dee;
273 dee *= alpha1;
274 alpha1 = alphanew;
275 alphanew = alpha2 - (W2[j]*W2[j])*dee;
276 dee /= alphanew;
277 gamma2 = W2[j] * dee;
278 dee *= alpha2;
279 d[j] = dee;
280 alpha2 = alphanew;
281
282 k1 = W1[j];
283 k2 = W2[j];
284 for (p=j+1; p<n; p++) {
285 ell = L[p*nskip+j];
286 Wp = W1[p] - k1 * ell;
287 ell += gamma1 * Wp;
288 W1[p] = Wp;
289 Wp = W2[p] - k2 * ell;
290 ell -= gamma2 * Wp;
291 W2[p] = Wp;
292 L[p*nskip+j] = ell;
293 }
294 }
295}
296
297
298// macros for dLDLTRemove() for accessing A - either access the matrix
299// directly or access it via row pointers. we are only supposed to reference
300// the lower triangle of A (it is symmetric), but indexes i and j come from
301// permutation vectors so they are not predictable. so do a test on the
302// indexes - this should not slow things down too much, as we don't do this
303// in an inner loop.
304
305#define _GETA(i,j) (A[i][j])
306//#define _GETA(i,j) (A[(i)*nskip+(j)])
307#define GETA(i,j) ((i > j) ? _GETA(i,j) : _GETA(j,i))
308
309
310void dLDLTRemove (dReal **A, const int *p, dReal *L, dReal *d,
311 int n1, int n2, int r, int nskip)
312{
313 int i;
314 dAASSERT(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
315 n1 >= n2 && nskip >= n1);
316 #ifndef dNODEBUG
317 for (i=0; i<n2; i++) dIASSERT(p[i] >= 0 && p[i] < n1);
318 #endif
319
320 if (r==n2-1) {
321 return; // deleting last row/col is easy
322 }
323 else if (r==0) {
324 dReal *a = (dReal*) ALLOCA (n2 * sizeof(dReal));
325 for (i=0; i<n2; i++) a[i] = -GETA(p[i],p[0]);
326 a[0] += REAL(1.0);
327 dLDLTAddTL (L,d,a,n2,nskip);
328 }
329 else {
330 dReal *t = (dReal*) ALLOCA (r * sizeof(dReal));
331 dReal *a = (dReal*) ALLOCA ((n2-r) * sizeof(dReal));
332 for (i=0; i<r; i++) t[i] = L[r*nskip+i] / d[i];
333 for (i=0; i<(n2-r); i++)
334 a[i] = dDot(L+(r+i)*nskip,t,r) - GETA(p[r+i],p[r]);
335 a[0] += REAL(1.0);
336 dLDLTAddTL (L + r*nskip+r, d+r, a, n2-r, nskip);
337 }
338
339 // snip out row/column r from L and d
340 dRemoveRowCol (L,n2,nskip,r);
341 if (r < (n2-1)) memmove (d+r,d+r+1,(n2-r-1)*sizeof(dReal));
342}
343
344
345void dRemoveRowCol (dReal *A, int n, int nskip, int r)
346{
347 int i;
348 dAASSERT(A && n > 0 && nskip >= n && r >= 0 && r < n);
349 if (r >= n-1) return;
350 if (r > 0) {
351 for (i=0; i<r; i++)
352 memmove (A+i*nskip+r,A+i*nskip+r+1,(n-r-1)*sizeof(dReal));
353 for (i=r; i<(n-1); i++)
354 memcpy (A+i*nskip,A+i*nskip+nskip,r*sizeof(dReal));
355 }
356 for (i=r; i<(n-1); i++)
357 memcpy (A+i*nskip+r,A+i*nskip+nskip+r+1,(n-r-1)*sizeof(dReal));
358}
diff --git a/libraries/ode-0.9/ode/src/memory.cpp b/libraries/ode-0.9/ode/src/memory.cpp
deleted file mode 100644
index 60bb5b6..0000000
--- a/libraries/ode-0.9/ode/src/memory.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/memory.h>
25#include <ode/error.h>
26
27
28static dAllocFunction *allocfn = 0;
29static dReallocFunction *reallocfn = 0;
30static dFreeFunction *freefn = 0;
31
32
33
34void dSetAllocHandler (dAllocFunction *fn)
35{
36 allocfn = fn;
37}
38
39
40void dSetReallocHandler (dReallocFunction *fn)
41{
42 reallocfn = fn;
43}
44
45
46void dSetFreeHandler (dFreeFunction *fn)
47{
48 freefn = fn;
49}
50
51
52dAllocFunction *dGetAllocHandler()
53{
54 return allocfn;
55}
56
57
58dReallocFunction *dGetReallocHandler()
59{
60 return reallocfn;
61}
62
63
64dFreeFunction *dGetFreeHandler()
65{
66 return freefn;
67}
68
69
70void * dAlloc (size_t size)
71{
72 if (allocfn) return allocfn (size); else return malloc (size);
73}
74
75
76void * dRealloc (void *ptr, size_t oldsize, size_t newsize)
77{
78 if (reallocfn) return reallocfn (ptr,oldsize,newsize);
79 else return realloc (ptr,newsize);
80}
81
82
83void dFree (void *ptr, size_t size)
84{
85 if (!ptr) return;
86 if (freefn) freefn (ptr,size); else free (ptr);
87}
diff --git a/libraries/ode-0.9/ode/src/misc.cpp b/libraries/ode-0.9/ode/src/misc.cpp
deleted file mode 100644
index 1a6f263..0000000
--- a/libraries/ode-0.9/ode/src/misc.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/misc.h>
25#include <ode/matrix.h>
26
27//****************************************************************************
28// random numbers
29
30static unsigned long seed = 0;
31
32unsigned long dRand()
33{
34 seed = (1664525L*seed + 1013904223L) & 0xffffffff;
35 return seed;
36}
37
38
39unsigned long dRandGetSeed()
40{
41 return seed;
42}
43
44
45void dRandSetSeed (unsigned long s)
46{
47 seed = s;
48}
49
50
51int dTestRand()
52{
53 unsigned long oldseed = seed;
54 int ret = 1;
55 seed = 0;
56 if (dRand() != 0x3c6ef35f || dRand() != 0x47502932 ||
57 dRand() != 0xd1ccf6e9 || dRand() != 0xaaf95334 ||
58 dRand() != 0x6252e503) ret = 0;
59 seed = oldseed;
60 return ret;
61}
62
63
64// adam's all-int straightforward(?) dRandInt (0..n-1)
65int dRandInt (int n)
66{
67 // seems good; xor-fold and modulus
68 const unsigned long un = n;
69 unsigned long r = dRand();
70
71 // note: probably more aggressive than it needs to be -- might be
72 // able to get away without one or two of the innermost branches.
73 if (un <= 0x00010000UL) {
74 r ^= (r >> 16);
75 if (un <= 0x00000100UL) {
76 r ^= (r >> 8);
77 if (un <= 0x00000010UL) {
78 r ^= (r >> 4);
79 if (un <= 0x00000004UL) {
80 r ^= (r >> 2);
81 if (un <= 0x00000002UL) {
82 r ^= (r >> 1);
83 }
84 }
85 }
86 }
87 }
88
89 return (int) (r % un);
90}
91
92
93dReal dRandReal()
94{
95 return ((dReal) dRand()) / ((dReal) 0xffffffff);
96}
97
98//****************************************************************************
99// matrix utility stuff
100
101void dPrintMatrix (const dReal *A, int n, int m, char *fmt, FILE *f)
102{
103 int i,j;
104 int skip = dPAD(m);
105 for (i=0; i<n; i++) {
106 for (j=0; j<m; j++) fprintf (f,fmt,A[i*skip+j]);
107 fprintf (f,"\n");
108 }
109}
110
111
112void dMakeRandomVector (dReal *A, int n, dReal range)
113{
114 int i;
115 for (i=0; i<n; i++) A[i] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
116}
117
118
119void dMakeRandomMatrix (dReal *A, int n, int m, dReal range)
120{
121 int i,j;
122 int skip = dPAD(m);
123 dSetZero (A,n*skip);
124 for (i=0; i<n; i++) {
125 for (j=0; j<m; j++) A[i*skip+j] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
126 }
127}
128
129
130void dClearUpperTriangle (dReal *A, int n)
131{
132 int i,j;
133 int skip = dPAD(n);
134 for (i=0; i<n; i++) {
135 for (j=i+1; j<n; j++) A[i*skip+j] = 0;
136 }
137}
138
139
140dReal dMaxDifference (const dReal *A, const dReal *B, int n, int m)
141{
142 int i,j;
143 int skip = dPAD(m);
144 dReal diff,max;
145 max = 0;
146 for (i=0; i<n; i++) {
147 for (j=0; j<m; j++) {
148 diff = dFabs(A[i*skip+j] - B[i*skip+j]);
149 if (diff > max) max = diff;
150 }
151 }
152 return max;
153}
154
155
156dReal dMaxDifferenceLowerTriangle (const dReal *A, const dReal *B, int n)
157{
158 int i,j;
159 int skip = dPAD(n);
160 dReal diff,max;
161 max = 0;
162 for (i=0; i<n; i++) {
163 for (j=0; j<=i; j++) {
164 diff = dFabs(A[i*skip+j] - B[i*skip+j]);
165 if (diff > max) max = diff;
166 }
167 }
168 return max;
169}
diff --git a/libraries/ode-0.9/ode/src/objects.h b/libraries/ode-0.9/ode/src/objects.h
deleted file mode 100644
index f286e2d..0000000
--- a/libraries/ode-0.9/ode/src/objects.h
+++ /dev/null
@@ -1,138 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23// object, body, and world structs.
24
25
26#ifndef _ODE_OBJECT_H_
27#define _ODE_OBJECT_H_
28
29#include <ode/common.h>
30#include <ode/memory.h>
31#include <ode/mass.h>
32#include "array.h"
33
34
35// some body flags
36
37enum {
38 dxBodyFlagFiniteRotation = 1, // use finite rotations
39 dxBodyFlagFiniteRotationAxis = 2, // use finite rotations only along axis
40 dxBodyDisabled = 4, // body is disabled
41 dxBodyNoGravity = 8, // body is not influenced by gravity
42 dxBodyAutoDisable = 16 // enable auto-disable on body
43};
44
45
46// base class that does correct object allocation / deallocation
47
48struct dBase {
49 void *operator new (size_t size) { return dAlloc (size); }
50 void operator delete (void *ptr, size_t size) { dFree (ptr,size); }
51 void *operator new[] (size_t size) { return dAlloc (size); }
52 void operator delete[] (void *ptr, size_t size) { dFree (ptr,size); }
53};
54
55
56// base class for bodies and joints
57
58struct dObject : public dBase {
59 dxWorld *world; // world this object is in
60 dObject *next; // next object of this type in list
61 dObject **tome; // pointer to previous object's next ptr
62 void *userdata; // user settable data
63 int tag; // used by dynamics algorithms
64};
65
66
67// auto disable parameters
68struct dxAutoDisable {
69 dReal idle_time; // time the body needs to be idle to auto-disable it
70 int idle_steps; // steps the body needs to be idle to auto-disable it
71 dReal linear_average_threshold; // linear (squared) average velocity threshold
72 dReal angular_average_threshold; // angular (squared) average velocity threshold
73 unsigned int average_samples; // size of the average_lvel and average_avel buffers
74};
75
76
77// quick-step parameters
78struct dxQuickStepParameters {
79 int num_iterations; // number of SOR iterations to perform
80 dReal w; // the SOR over-relaxation parameter
81};
82
83
84// contact generation parameters
85struct dxContactParameters {
86 dReal max_vel; // maximum correcting velocity
87 dReal min_depth; // thickness of 'surface layer'
88};
89
90
91
92// position vector and rotation matrix for geometry objects that are not
93// connected to bodies.
94
95struct dxPosR {
96 dVector3 pos;
97 dMatrix3 R;
98};
99
100struct dxBody : public dObject {
101 dxJointNode *firstjoint; // list of attached joints
102 int flags; // some dxBodyFlagXXX flags
103 dGeomID geom; // first collision geom associated with body
104 dMass mass; // mass parameters about POR
105 dMatrix3 invI; // inverse of mass.I
106 dReal invMass; // 1 / mass.mass
107 dxPosR posr; // position and orientation of point of reference
108 dQuaternion q; // orientation quaternion
109 dVector3 lvel,avel; // linear and angular velocity of POR
110 dVector3 facc,tacc; // force and torque accumulators
111 dVector3 finite_rot_axis; // finite rotation axis, unit length or 0=none
112
113 // auto-disable information
114 dxAutoDisable adis; // auto-disable parameters
115 dReal adis_timeleft; // time left to be idle
116 int adis_stepsleft; // steps left to be idle
117 dVector3* average_lvel_buffer; // buffer for the linear average velocity calculation
118 dVector3* average_avel_buffer; // buffer for the angular average velocity calculation
119 unsigned int average_counter; // counter/index to fill the average-buffers
120 int average_ready; // indicates ( with = 1 ), if the Body's buffers are ready for average-calculations
121};
122
123
124struct dxWorld : public dBase {
125 dxBody *firstbody; // body linked list
126 dxJoint *firstjoint; // joint linked list
127 int nb,nj; // number of bodies and joints in lists
128 dVector3 gravity; // gravity vector (m/s/s)
129 dReal global_erp; // global error reduction parameter
130 dReal global_cfm; // global costraint force mixing parameter
131 dxAutoDisable adis; // auto-disable parameters
132 int adis_flag; // auto-disable flag for new bodies
133 dxQuickStepParameters qs;
134 dxContactParameters contactp;
135};
136
137
138#endif
diff --git a/libraries/ode-0.9/ode/src/obstack.cpp b/libraries/ode-0.9/ode/src/obstack.cpp
deleted file mode 100644
index 0840396..0000000
--- a/libraries/ode-0.9/ode/src/obstack.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/common.h>
24#include <ode/error.h>
25#include <ode/memory.h>
26#include "obstack.h"
27
28//****************************************************************************
29// macros and constants
30
31#define ROUND_UP_OFFSET_TO_EFFICIENT_SIZE(arena,ofs) \
32 ofs = (size_t) (dEFFICIENT_SIZE( ((intP)(arena)) + ofs ) - ((intP)(arena)) );
33
34#define MAX_ALLOC_SIZE \
35 ((size_t)(dOBSTACK_ARENA_SIZE - sizeof (Arena) - EFFICIENT_ALIGNMENT + 1))
36
37//****************************************************************************
38// dObStack
39
40dObStack::dObStack()
41{
42 first = 0;
43 last = 0;
44 current_arena = 0;
45 current_ofs = 0;
46}
47
48
49dObStack::~dObStack()
50{
51 // free all arenas
52 Arena *a,*nexta;
53 a = first;
54 while (a) {
55 nexta = a->next;
56 dFree (a,dOBSTACK_ARENA_SIZE);
57 a = nexta;
58 }
59}
60
61
62void *dObStack::alloc (int num_bytes)
63{
64 if ((size_t)num_bytes > MAX_ALLOC_SIZE) dDebug (0,"num_bytes too large");
65
66 // allocate or move to a new arena if necessary
67 if (!first) {
68 // allocate the first arena if necessary
69 first = last = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE);
70 first->next = 0;
71 first->used = sizeof (Arena);
72 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (first,first->used);
73 }
74 else {
75 // we already have one or more arenas, see if a new arena must be used
76 if ((last->used + num_bytes) > dOBSTACK_ARENA_SIZE) {
77 if (!last->next) {
78 last->next = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE);
79 last->next->next = 0;
80 }
81 last = last->next;
82 last->used = sizeof (Arena);
83 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (last,last->used);
84 }
85 }
86
87 // allocate an area in the arena
88 char *c = ((char*) last) + last->used;
89 last->used += num_bytes;
90 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (last,last->used);
91 return c;
92}
93
94
95void dObStack::freeAll()
96{
97 last = first;
98 if (first) {
99 first->used = sizeof(Arena);
100 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (first,first->used);
101 }
102}
103
104
105void *dObStack::rewind()
106{
107 current_arena = first;
108 current_ofs = sizeof (Arena);
109 if (current_arena) {
110 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs)
111 return ((char*) current_arena) + current_ofs;
112 }
113 else return 0;
114}
115
116
117void *dObStack::next (int num_bytes)
118{
119 // this functions like alloc, except that no new storage is ever allocated
120 if (!current_arena) return 0;
121 current_ofs += num_bytes;
122 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs);
123 if (current_ofs >= current_arena->used) {
124 current_arena = current_arena->next;
125 if (!current_arena) return 0;
126 current_ofs = sizeof (Arena);
127 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs);
128 }
129 return ((char*) current_arena) + current_ofs;
130}
diff --git a/libraries/ode-0.9/ode/src/obstack.h b/libraries/ode-0.9/ode/src/obstack.h
deleted file mode 100644
index b5f715b..0000000
--- a/libraries/ode-0.9/ode/src/obstack.h
+++ /dev/null
@@ -1,68 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifndef _ODE_OBSTACK_H_
24#define _ODE_OBSTACK_H_
25
26#include "objects.h"
27
28// each obstack Arena pointer points to a block of this many bytes
29#define dOBSTACK_ARENA_SIZE 16384
30
31
32struct dObStack : public dBase {
33 struct Arena {
34 Arena *next; // next arena in linked list
35 size_t used; // total number of bytes used in this arena, counting
36 }; // this header
37
38 Arena *first; // head of the arena linked list. 0 if no arenas yet
39 Arena *last; // arena where blocks are currently being allocated
40
41 // used for iterator
42 Arena *current_arena;
43 size_t current_ofs;
44
45 dObStack();
46 ~dObStack();
47
48 void *alloc (int num_bytes);
49 // allocate a block in the last arena, allocating a new arena if necessary.
50 // it is a runtime error if num_bytes is larger than the arena size.
51
52 void freeAll();
53 // free all blocks in all arenas. this does not deallocate the arenas
54 // themselves, so future alloc()s will reuse them.
55
56 void *rewind();
57 // rewind the obstack iterator, and return the address of the first
58 // allocated block. return 0 if there are no allocated blocks.
59
60 void *next (int num_bytes);
61 // return the address of the next allocated block. 'num_bytes' is the size
62 // of the previous block. this returns null if there are no more arenas.
63 // the sequence of 'num_bytes' parameters passed to next() during a
64 // traversal of the list must exactly match the parameters passed to alloc().
65};
66
67
68#endif
diff --git a/libraries/ode-0.9/ode/src/ode.cpp b/libraries/ode-0.9/ode/src/ode.cpp
deleted file mode 100644
index 46f559a..0000000
--- a/libraries/ode-0.9/ode/src/ode.cpp
+++ /dev/null
@@ -1,1732 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifdef _MSC_VER
24#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
25#endif
26
27// this source file is mostly concerned with the data structures, not the
28// numerics.
29
30#include "objects.h"
31#include <ode/ode.h>
32#include "joint.h"
33#include <ode/odemath.h>
34#include <ode/matrix.h>
35#include "step.h"
36#include "quickstep.h"
37#include "util.h"
38#include <ode/memory.h>
39#include <ode/error.h>
40
41// misc defines
42#define ALLOCA dALLOCA16
43
44//****************************************************************************
45// utility
46
47static inline void initObject (dObject *obj, dxWorld *w)
48{
49 obj->world = w;
50 obj->next = 0;
51 obj->tome = 0;
52 obj->userdata = 0;
53 obj->tag = 0;
54}
55
56
57// add an object `obj' to the list who's head pointer is pointed to by `first'.
58
59static inline void addObjectToList (dObject *obj, dObject **first)
60{
61 obj->next = *first;
62 obj->tome = first;
63 if (*first) (*first)->tome = &obj->next;
64 (*first) = obj;
65}
66
67
68// remove the object from the linked list
69
70static inline void removeObjectFromList (dObject *obj)
71{
72 if (obj->next) obj->next->tome = obj->tome;
73 *(obj->tome) = obj->next;
74 // safeguard
75 obj->next = 0;
76 obj->tome = 0;
77}
78
79
80// remove the joint from neighbour lists of all connected bodies
81
82static void removeJointReferencesFromAttachedBodies (dxJoint *j)
83{
84 for (int i=0; i<2; i++) {
85 dxBody *body = j->node[i].body;
86 if (body) {
87 dxJointNode *n = body->firstjoint;
88 dxJointNode *last = 0;
89 while (n) {
90 if (n->joint == j) {
91 if (last) last->next = n->next;
92 else body->firstjoint = n->next;
93 break;
94 }
95 last = n;
96 n = n->next;
97 }
98 }
99 }
100 j->node[0].body = 0;
101 j->node[0].next = 0;
102 j->node[1].body = 0;
103 j->node[1].next = 0;
104}
105
106//****************************************************************************
107// debugging
108
109// see if an object list loops on itself (if so, it's bad).
110
111static int listHasLoops (dObject *first)
112{
113 if (first==0 || first->next==0) return 0;
114 dObject *a=first,*b=first->next;
115 int skip=0;
116 while (b) {
117 if (a==b) return 1;
118 b = b->next;
119 if (skip) a = a->next;
120 skip ^= 1;
121 }
122 return 0;
123}
124
125
126// check the validity of the world data structures
127
128static void checkWorld (dxWorld *w)
129{
130 dxBody *b;
131 dxJoint *j;
132
133 // check there are no loops
134 if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops");
135 if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops");
136
137 // check lists are well formed (check `tome' pointers)
138 for (b=w->firstbody; b; b=(dxBody*)b->next) {
139 if (b->next && b->next->tome != &b->next)
140 dDebug (0,"bad tome pointer in body list");
141 }
142 for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
143 if (j->next && j->next->tome != &j->next)
144 dDebug (0,"bad tome pointer in joint list");
145 }
146
147 // check counts
148 int n = 0;
149 for (b=w->firstbody; b; b=(dxBody*)b->next) n++;
150 if (w->nb != n) dDebug (0,"body count incorrect");
151 n = 0;
152 for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++;
153 if (w->nj != n) dDebug (0,"joint count incorrect");
154
155 // set all tag values to a known value
156 static int count = 0;
157 count++;
158 for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count;
159 for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count;
160
161 // check all body/joint world pointers are ok
162 for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w)
163 dDebug (0,"bad world pointer in body list");
164 for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w)
165 dDebug (0,"bad world pointer in joint list");
166
167 /*
168 // check for half-connected joints - actually now these are valid
169 for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
170 if (j->node[0].body || j->node[1].body) {
171 if (!(j->node[0].body && j->node[1].body))
172 dDebug (0,"half connected joint found");
173 }
174 }
175 */
176
177 // check that every joint node appears in the joint lists of both bodies it
178 // attaches
179 for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
180 for (int i=0; i<2; i++) {
181 if (j->node[i].body) {
182 int ok = 0;
183 for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) {
184 if (n->joint == j) ok = 1;
185 }
186 if (ok==0) dDebug (0,"joint not in joint list of attached body");
187 }
188 }
189 }
190
191 // check all body joint lists (correct body ptrs)
192 for (b=w->firstbody; b; b=(dxBody*)b->next) {
193 for (dxJointNode *n=b->firstjoint; n; n=n->next) {
194 if (&n->joint->node[0] == n) {
195 if (n->joint->node[1].body != b)
196 dDebug (0,"bad body pointer in joint node of body list (1)");
197 }
198 else {
199 if (n->joint->node[0].body != b)
200 dDebug (0,"bad body pointer in joint node of body list (2)");
201 }
202 if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body");
203 }
204 }
205
206 // check all body pointers in joints, check they are distinct
207 for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
208 if (j->node[0].body && (j->node[0].body == j->node[1].body))
209 dDebug (0,"non-distinct body pointers in joint");
210 if ((j->node[0].body && j->node[0].body->tag != count) ||
211 (j->node[1].body && j->node[1].body->tag != count))
212 dDebug (0,"bad body pointer in joint");
213 }
214}
215
216
217void dWorldCheck (dxWorld *w)
218{
219 checkWorld (w);
220}
221
222//****************************************************************************
223// body
224dxWorld* dBodyGetWorld (dxBody* b)
225{
226 dAASSERT (b);
227 return b->world;
228}
229
230dxBody *dBodyCreate (dxWorld *w)
231{
232 dAASSERT (w);
233 dxBody *b = new dxBody;
234 initObject (b,w);
235 b->firstjoint = 0;
236 b->flags = 0;
237 b->geom = 0;
238 b->average_lvel_buffer = 0;
239 b->average_avel_buffer = 0;
240 dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0);
241 dSetZero (b->invI,4*3);
242 b->invI[0] = 1;
243 b->invI[5] = 1;
244 b->invI[10] = 1;
245 b->invMass = 1;
246 dSetZero (b->posr.pos,4);
247 dSetZero (b->q,4);
248 b->q[0] = 1;
249 dRSetIdentity (b->posr.R);
250 dSetZero (b->lvel,4);
251 dSetZero (b->avel,4);
252 dSetZero (b->facc,4);
253 dSetZero (b->tacc,4);
254 dSetZero (b->finite_rot_axis,4);
255 addObjectToList (b,(dObject **) &w->firstbody);
256 w->nb++;
257
258 // set auto-disable parameters
259 b->average_avel_buffer = b->average_lvel_buffer = 0; // no buffer at beginnin
260 dBodySetAutoDisableDefaults (b); // must do this after adding to world
261 b->adis_stepsleft = b->adis.idle_steps;
262 b->adis_timeleft = b->adis.idle_time;
263 b->average_counter = 0;
264 b->average_ready = 0; // average buffer not filled on the beginning
265 dBodySetAutoDisableAverageSamplesCount(b, b->adis.average_samples);
266
267 return b;
268}
269
270
271void dBodyDestroy (dxBody *b)
272{
273 dAASSERT (b);
274
275 // all geoms that link to this body must be notified that the body is about
276 // to disappear. note that the call to dGeomSetBody(geom,0) will result in
277 // dGeomGetBodyNext() returning 0 for the body, so we must get the next body
278 // before setting the body to 0.
279 dxGeom *next_geom = 0;
280 for (dxGeom *geom = b->geom; geom; geom = next_geom) {
281 next_geom = dGeomGetBodyNext (geom);
282 dGeomSetBody (geom,0);
283 }
284
285 // detach all neighbouring joints, then delete this body.
286 dxJointNode *n = b->firstjoint;
287 while (n) {
288 // sneaky trick to speed up removal of joint references (black magic)
289 n->joint->node[(n == n->joint->node)].body = 0;
290
291 dxJointNode *next = n->next;
292 n->next = 0;
293 removeJointReferencesFromAttachedBodies (n->joint);
294 n = next;
295 }
296 removeObjectFromList (b);
297 b->world->nb--;
298
299 // delete the average buffers
300 if(b->average_lvel_buffer)
301 {
302 delete[] (b->average_lvel_buffer);
303 b->average_lvel_buffer = 0;
304 }
305 if(b->average_avel_buffer)
306 {
307 delete[] (b->average_avel_buffer);
308 b->average_avel_buffer = 0;
309 }
310
311 delete b;
312}
313
314
315void dBodySetData (dBodyID b, void *data)
316{
317 dAASSERT (b);
318 b->userdata = data;
319}
320
321
322void *dBodyGetData (dBodyID b)
323{
324 dAASSERT (b);
325 return b->userdata;
326}
327
328
329void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z)
330{
331 dAASSERT (b);
332 b->posr.pos[0] = x;
333 b->posr.pos[1] = y;
334 b->posr.pos[2] = z;
335
336 // notify all attached geoms that this body has moved
337 for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
338 dGeomMoved (geom);
339}
340
341
342void dBodySetRotation (dBodyID b, const dMatrix3 R)
343{
344 dAASSERT (b && R);
345 dQuaternion q;
346 dRtoQ (R,q);
347 dNormalize4 (q);
348 b->q[0] = q[0];
349 b->q[1] = q[1];
350 b->q[2] = q[2];
351 b->q[3] = q[3];
352 dQtoR (b->q,b->posr.R);
353
354 // notify all attached geoms that this body has moved
355 for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
356 dGeomMoved (geom);
357}
358
359
360void dBodySetQuaternion (dBodyID b, const dQuaternion q)
361{
362 dAASSERT (b && q);
363 b->q[0] = q[0];
364 b->q[1] = q[1];
365 b->q[2] = q[2];
366 b->q[3] = q[3];
367 dNormalize4 (b->q);
368 dQtoR (b->q,b->posr.R);
369
370 // notify all attached geoms that this body has moved
371 for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
372 dGeomMoved (geom);
373}
374
375
376void dBodySetLinearVel (dBodyID b, dReal x, dReal y, dReal z)
377{
378 dAASSERT (b);
379 b->lvel[0] = x;
380 b->lvel[1] = y;
381 b->lvel[2] = z;
382}
383
384
385void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z)
386{
387 dAASSERT (b);
388 b->avel[0] = x;
389 b->avel[1] = y;
390 b->avel[2] = z;
391}
392
393
394const dReal * dBodyGetPosition (dBodyID b)
395{
396 dAASSERT (b);
397 return b->posr.pos;
398}
399
400
401void dBodyCopyPosition (dBodyID b, dVector3 pos)
402{
403 dAASSERT (b);
404 dReal* src = b->posr.pos;
405 pos[0] = src[0];
406 pos[1] = src[1];
407 pos[2] = src[2];
408}
409
410
411const dReal * dBodyGetRotation (dBodyID b)
412{
413 dAASSERT (b);
414 return b->posr.R;
415}
416
417
418void dBodyCopyRotation (dBodyID b, dMatrix3 R)
419{
420 dAASSERT (b);
421 const dReal* src = b->posr.R;
422 R[0] = src[0];
423 R[1] = src[1];
424 R[2] = src[2];
425 R[3] = src[3];
426 R[4] = src[4];
427 R[5] = src[5];
428 R[6] = src[6];
429 R[7] = src[7];
430 R[8] = src[8];
431 R[9] = src[9];
432 R[10] = src[10];
433 R[11] = src[11];
434}
435
436
437const dReal * dBodyGetQuaternion (dBodyID b)
438{
439 dAASSERT (b);
440 return b->q;
441}
442
443
444void dBodyCopyQuaternion (dBodyID b, dQuaternion quat)
445{
446 dAASSERT (b);
447 dReal* src = b->q;
448 quat[0] = src[0];
449 quat[1] = src[1];
450 quat[2] = src[2];
451 quat[3] = src[3];
452}
453
454
455const dReal * dBodyGetLinearVel (dBodyID b)
456{
457 dAASSERT (b);
458 return b->lvel;
459}
460
461
462const dReal * dBodyGetAngularVel (dBodyID b)
463{
464 dAASSERT (b);
465 return b->avel;
466}
467
468
469void dBodySetMass (dBodyID b, const dMass *mass)
470{
471 dAASSERT (b && mass );
472 dIASSERT(dMassCheck(mass));
473
474 // The centre of mass must be at the origin.
475 // Use dMassTranslate( mass, -mass->c[0], -mass->c[1], -mass->c[2] ) to correct it.
476 dUASSERT( fabs( mass->c[0] ) <= dEpsilon &&
477 fabs( mass->c[1] ) <= dEpsilon &&
478 fabs( mass->c[2] ) <= dEpsilon, "The centre of mass must be at the origin." )
479
480 memcpy (&b->mass,mass,sizeof(dMass));
481 if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) {
482 dDEBUGMSG ("inertia must be positive definite!");
483 dRSetIdentity (b->invI);
484 }
485 b->invMass = dRecip(b->mass.mass);
486}
487
488
489void dBodyGetMass (dBodyID b, dMass *mass)
490{
491 dAASSERT (b && mass);
492 memcpy (mass,&b->mass,sizeof(dMass));
493}
494
495
496void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz)
497{
498 dAASSERT (b);
499 b->facc[0] += fx;
500 b->facc[1] += fy;
501 b->facc[2] += fz;
502}
503
504
505void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
506{
507 dAASSERT (b);
508 b->tacc[0] += fx;
509 b->tacc[1] += fy;
510 b->tacc[2] += fz;
511}
512
513
514void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz)
515{
516 dAASSERT (b);
517 dVector3 t1,t2;
518 t1[0] = fx;
519 t1[1] = fy;
520 t1[2] = fz;
521 t1[3] = 0;
522 dMULTIPLY0_331 (t2,b->posr.R,t1);
523 b->facc[0] += t2[0];
524 b->facc[1] += t2[1];
525 b->facc[2] += t2[2];
526}
527
528
529void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
530{
531 dAASSERT (b);
532 dVector3 t1,t2;
533 t1[0] = fx;
534 t1[1] = fy;
535 t1[2] = fz;
536 t1[3] = 0;
537 dMULTIPLY0_331 (t2,b->posr.R,t1);
538 b->tacc[0] += t2[0];
539 b->tacc[1] += t2[1];
540 b->tacc[2] += t2[2];
541}
542
543
544void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
545 dReal px, dReal py, dReal pz)
546{
547 dAASSERT (b);
548 b->facc[0] += fx;
549 b->facc[1] += fy;
550 b->facc[2] += fz;
551 dVector3 f,q;
552 f[0] = fx;
553 f[1] = fy;
554 f[2] = fz;
555 q[0] = px - b->posr.pos[0];
556 q[1] = py - b->posr.pos[1];
557 q[2] = pz - b->posr.pos[2];
558 dCROSS (b->tacc,+=,q,f);
559}
560
561
562void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
563 dReal px, dReal py, dReal pz)
564{
565 dAASSERT (b);
566 dVector3 prel,f,p;
567 f[0] = fx;
568 f[1] = fy;
569 f[2] = fz;
570 f[3] = 0;
571 prel[0] = px;
572 prel[1] = py;
573 prel[2] = pz;
574 prel[3] = 0;
575 dMULTIPLY0_331 (p,b->posr.R,prel);
576 b->facc[0] += f[0];
577 b->facc[1] += f[1];
578 b->facc[2] += f[2];
579 dCROSS (b->tacc,+=,p,f);
580}
581
582
583void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
584 dReal px, dReal py, dReal pz)
585{
586 dAASSERT (b);
587 dVector3 frel,f;
588 frel[0] = fx;
589 frel[1] = fy;
590 frel[2] = fz;
591 frel[3] = 0;
592 dMULTIPLY0_331 (f,b->posr.R,frel);
593 b->facc[0] += f[0];
594 b->facc[1] += f[1];
595 b->facc[2] += f[2];
596 dVector3 q;
597 q[0] = px - b->posr.pos[0];
598 q[1] = py - b->posr.pos[1];
599 q[2] = pz - b->posr.pos[2];
600 dCROSS (b->tacc,+=,q,f);
601}
602
603
604void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
605 dReal px, dReal py, dReal pz)
606{
607 dAASSERT (b);
608 dVector3 frel,prel,f,p;
609 frel[0] = fx;
610 frel[1] = fy;
611 frel[2] = fz;
612 frel[3] = 0;
613 prel[0] = px;
614 prel[1] = py;
615 prel[2] = pz;
616 prel[3] = 0;
617 dMULTIPLY0_331 (f,b->posr.R,frel);
618 dMULTIPLY0_331 (p,b->posr.R,prel);
619 b->facc[0] += f[0];
620 b->facc[1] += f[1];
621 b->facc[2] += f[2];
622 dCROSS (b->tacc,+=,p,f);
623}
624
625
626const dReal * dBodyGetForce (dBodyID b)
627{
628 dAASSERT (b);
629 return b->facc;
630}
631
632
633const dReal * dBodyGetTorque (dBodyID b)
634{
635 dAASSERT (b);
636 return b->tacc;
637}
638
639
640void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z)
641{
642 dAASSERT (b);
643 b->facc[0] = x;
644 b->facc[1] = y;
645 b->facc[2] = z;
646}
647
648
649void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z)
650{
651 dAASSERT (b);
652 b->tacc[0] = x;
653 b->tacc[1] = y;
654 b->tacc[2] = z;
655}
656
657
658void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz,
659 dVector3 result)
660{
661 dAASSERT (b);
662 dVector3 prel,p;
663 prel[0] = px;
664 prel[1] = py;
665 prel[2] = pz;
666 prel[3] = 0;
667 dMULTIPLY0_331 (p,b->posr.R,prel);
668 result[0] = p[0] + b->posr.pos[0];
669 result[1] = p[1] + b->posr.pos[1];
670 result[2] = p[2] + b->posr.pos[2];
671}
672
673
674void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz,
675 dVector3 result)
676{
677 dAASSERT (b);
678 dVector3 prel,p;
679 prel[0] = px;
680 prel[1] = py;
681 prel[2] = pz;
682 prel[3] = 0;
683 dMULTIPLY0_331 (p,b->posr.R,prel);
684 result[0] = b->lvel[0];
685 result[1] = b->lvel[1];
686 result[2] = b->lvel[2];
687 dCROSS (result,+=,b->avel,p);
688}
689
690
691void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz,
692 dVector3 result)
693{
694 dAASSERT (b);
695 dVector3 p;
696 p[0] = px - b->posr.pos[0];
697 p[1] = py - b->posr.pos[1];
698 p[2] = pz - b->posr.pos[2];
699 p[3] = 0;
700 result[0] = b->lvel[0];
701 result[1] = b->lvel[1];
702 result[2] = b->lvel[2];
703 dCROSS (result,+=,b->avel,p);
704}
705
706
707void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz,
708 dVector3 result)
709{
710 dAASSERT (b);
711 dVector3 prel;
712 prel[0] = px - b->posr.pos[0];
713 prel[1] = py - b->posr.pos[1];
714 prel[2] = pz - b->posr.pos[2];
715 prel[3] = 0;
716 dMULTIPLY1_331 (result,b->posr.R,prel);
717}
718
719
720void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz,
721 dVector3 result)
722{
723 dAASSERT (b);
724 dVector3 p;
725 p[0] = px;
726 p[1] = py;
727 p[2] = pz;
728 p[3] = 0;
729 dMULTIPLY0_331 (result,b->posr.R,p);
730}
731
732
733void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz,
734 dVector3 result)
735{
736 dAASSERT (b);
737 dVector3 p;
738 p[0] = px;
739 p[1] = py;
740 p[2] = pz;
741 p[3] = 0;
742 dMULTIPLY1_331 (result,b->posr.R,p);
743}
744
745
746void dBodySetFiniteRotationMode (dBodyID b, int mode)
747{
748 dAASSERT (b);
749 b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis);
750 if (mode) {
751 b->flags |= dxBodyFlagFiniteRotation;
752 if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 ||
753 b->finite_rot_axis[2] != 0) {
754 b->flags |= dxBodyFlagFiniteRotationAxis;
755 }
756 }
757}
758
759
760void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z)
761{
762 dAASSERT (b);
763 b->finite_rot_axis[0] = x;
764 b->finite_rot_axis[1] = y;
765 b->finite_rot_axis[2] = z;
766 if (x != 0 || y != 0 || z != 0) {
767 dNormalize3 (b->finite_rot_axis);
768 b->flags |= dxBodyFlagFiniteRotationAxis;
769 }
770 else {
771 b->flags &= ~dxBodyFlagFiniteRotationAxis;
772 }
773}
774
775
776int dBodyGetFiniteRotationMode (dBodyID b)
777{
778 dAASSERT (b);
779 return ((b->flags & dxBodyFlagFiniteRotation) != 0);
780}
781
782
783void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result)
784{
785 dAASSERT (b);
786 result[0] = b->finite_rot_axis[0];
787 result[1] = b->finite_rot_axis[1];
788 result[2] = b->finite_rot_axis[2];
789}
790
791
792int dBodyGetNumJoints (dBodyID b)
793{
794 dAASSERT (b);
795 int count=0;
796 for (dxJointNode *n=b->firstjoint; n; n=n->next, count++);
797 return count;
798}
799
800
801dJointID dBodyGetJoint (dBodyID b, int index)
802{
803 dAASSERT (b);
804 int i=0;
805 for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) {
806 if (i == index) return n->joint;
807 }
808 return 0;
809}
810
811
812void dBodyEnable (dBodyID b)
813{
814 dAASSERT (b);
815 b->flags &= ~dxBodyDisabled;
816 b->adis_stepsleft = b->adis.idle_steps;
817 b->adis_timeleft = b->adis.idle_time;
818 // no code for average-processing needed here
819}
820
821
822void dBodyDisable (dBodyID b)
823{
824 dAASSERT (b);
825 b->flags |= dxBodyDisabled;
826}
827
828
829int dBodyIsEnabled (dBodyID b)
830{
831 dAASSERT (b);
832 return ((b->flags & dxBodyDisabled) == 0);
833}
834
835
836void dBodySetGravityMode (dBodyID b, int mode)
837{
838 dAASSERT (b);
839 if (mode) b->flags &= ~dxBodyNoGravity;
840 else b->flags |= dxBodyNoGravity;
841}
842
843
844int dBodyGetGravityMode (dBodyID b)
845{
846 dAASSERT (b);
847 return ((b->flags & dxBodyNoGravity) == 0);
848}
849
850
851// body auto-disable functions
852
853dReal dBodyGetAutoDisableLinearThreshold (dBodyID b)
854{
855 dAASSERT(b);
856 return dSqrt (b->adis.linear_average_threshold);
857}
858
859
860void dBodySetAutoDisableLinearThreshold (dBodyID b, dReal linear_average_threshold)
861{
862 dAASSERT(b);
863 b->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold;
864}
865
866
867dReal dBodyGetAutoDisableAngularThreshold (dBodyID b)
868{
869 dAASSERT(b);
870 return dSqrt (b->adis.angular_average_threshold);
871}
872
873
874void dBodySetAutoDisableAngularThreshold (dBodyID b, dReal angular_average_threshold)
875{
876 dAASSERT(b);
877 b->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold;
878}
879
880
881int dBodyGetAutoDisableAverageSamplesCount (dBodyID b)
882{
883 dAASSERT(b);
884 return b->adis.average_samples;
885}
886
887
888void dBodySetAutoDisableAverageSamplesCount (dBodyID b, unsigned int average_samples_count)
889{
890 dAASSERT(b);
891 b->adis.average_samples = average_samples_count;
892 // update the average buffers
893 if(b->average_lvel_buffer)
894 {
895 delete[] b->average_lvel_buffer;
896 b->average_lvel_buffer = 0;
897 }
898 if(b->average_avel_buffer)
899 {
900 delete[] b->average_avel_buffer;
901 b->average_avel_buffer = 0;
902 }
903 if(b->adis.average_samples > 0)
904 {
905 b->average_lvel_buffer = new dVector3[b->adis.average_samples];
906 b->average_avel_buffer = new dVector3[b->adis.average_samples];
907 }
908 else
909 {
910 b->average_lvel_buffer = 0;
911 b->average_avel_buffer = 0;
912 }
913 // new buffer is empty
914 b->average_counter = 0;
915 b->average_ready = 0;
916}
917
918
919int dBodyGetAutoDisableSteps (dBodyID b)
920{
921 dAASSERT(b);
922 return b->adis.idle_steps;
923}
924
925
926void dBodySetAutoDisableSteps (dBodyID b, int steps)
927{
928 dAASSERT(b);
929 b->adis.idle_steps = steps;
930}
931
932
933dReal dBodyGetAutoDisableTime (dBodyID b)
934{
935 dAASSERT(b);
936 return b->adis.idle_time;
937}
938
939
940void dBodySetAutoDisableTime (dBodyID b, dReal time)
941{
942 dAASSERT(b);
943 b->adis.idle_time = time;
944}
945
946
947int dBodyGetAutoDisableFlag (dBodyID b)
948{
949 dAASSERT(b);
950 return ((b->flags & dxBodyAutoDisable) != 0);
951}
952
953
954void dBodySetAutoDisableFlag (dBodyID b, int do_auto_disable)
955{
956 dAASSERT(b);
957 if (!do_auto_disable)
958 {
959 b->flags &= ~dxBodyAutoDisable;
960 // (mg) we should also reset the IsDisabled state to correspond to the DoDisabling flag
961 b->flags &= ~dxBodyDisabled;
962 b->adis.idle_steps = dWorldGetAutoDisableSteps(b->world);
963 b->adis.idle_time = dWorldGetAutoDisableTime(b->world);
964 // resetting the average calculations too
965 dBodySetAutoDisableAverageSamplesCount(b, dWorldGetAutoDisableAverageSamplesCount(b->world) );
966 }
967 else
968 {
969 b->flags |= dxBodyAutoDisable;
970 }
971}
972
973
974void dBodySetAutoDisableDefaults (dBodyID b)
975{
976 dAASSERT(b);
977 dWorldID w = b->world;
978 dAASSERT(w);
979 b->adis = w->adis;
980 dBodySetAutoDisableFlag (b, w->adis_flag);
981}
982
983//****************************************************************************
984// joints
985
986static void dJointInit (dxWorld *w, dxJoint *j)
987{
988 dIASSERT (w && j);
989 initObject (j,w);
990 j->vtable = 0;
991 j->flags = 0;
992 j->node[0].joint = j;
993 j->node[0].body = 0;
994 j->node[0].next = 0;
995 j->node[1].joint = j;
996 j->node[1].body = 0;
997 j->node[1].next = 0;
998 dSetZero (j->lambda,6);
999 addObjectToList (j,(dObject **) &w->firstjoint);
1000 w->nj++;
1001}
1002
1003
1004static dxJoint *createJoint (dWorldID w, dJointGroupID group,
1005 dxJoint::Vtable *vtable)
1006{
1007 dIASSERT (w && vtable);
1008 dxJoint *j;
1009 if (group) {
1010 j = (dxJoint*) group->stack.alloc (vtable->size);
1011 group->num++;
1012 }
1013 else j = (dxJoint*) dAlloc (vtable->size);
1014 dJointInit (w,j);
1015 j->vtable = vtable;
1016 if (group) j->flags |= dJOINT_INGROUP;
1017 if (vtable->init) vtable->init (j);
1018 j->feedback = 0;
1019 return j;
1020}
1021
1022
1023dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group)
1024{
1025 dAASSERT (w);
1026 return createJoint (w,group,&__dball_vtable);
1027}
1028
1029
1030dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group)
1031{
1032 dAASSERT (w);
1033 return createJoint (w,group,&__dhinge_vtable);
1034}
1035
1036
1037dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group)
1038{
1039 dAASSERT (w);
1040 return createJoint (w,group,&__dslider_vtable);
1041}
1042
1043
1044dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group,
1045 const dContact *c)
1046{
1047 dAASSERT (w && c);
1048 dxJointContact *j = (dxJointContact *)
1049 createJoint (w,group,&__dcontact_vtable);
1050 j->contact = *c;
1051 return j;
1052}
1053
1054
1055dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group)
1056{
1057 dAASSERT (w);
1058 return createJoint (w,group,&__dhinge2_vtable);
1059}
1060
1061
1062dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group)
1063{
1064 dAASSERT (w);
1065 return createJoint (w,group,&__duniversal_vtable);
1066}
1067
1068dxJoint * dJointCreatePR (dWorldID w, dJointGroupID group)
1069{
1070 dAASSERT (w);
1071 return createJoint (w,group,&__dPR_vtable);
1072}
1073
1074dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group)
1075{
1076 dAASSERT (w);
1077 return createJoint (w,group,&__dfixed_vtable);
1078}
1079
1080
1081dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group)
1082{
1083 dAASSERT (w);
1084 return createJoint (w,group,&__dnull_vtable);
1085}
1086
1087
1088dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group)
1089{
1090 dAASSERT (w);
1091 return createJoint (w,group,&__damotor_vtable);
1092}
1093
1094dxJoint * dJointCreateLMotor (dWorldID w, dJointGroupID group)
1095{
1096 dAASSERT (w);
1097 return createJoint (w,group,&__dlmotor_vtable);
1098}
1099
1100dxJoint * dJointCreatePlane2D (dWorldID w, dJointGroupID group)
1101{
1102 dAASSERT (w);
1103 return createJoint (w,group,&__dplane2d_vtable);
1104}
1105
1106void dJointDestroy (dxJoint *j)
1107{
1108 dAASSERT (j);
1109 if (j->flags & dJOINT_INGROUP) return;
1110 removeJointReferencesFromAttachedBodies (j);
1111 removeObjectFromList (j);
1112 j->world->nj--;
1113 dFree (j,j->vtable->size);
1114}
1115
1116
1117dJointGroupID dJointGroupCreate (int max_size)
1118{
1119 // not any more ... dUASSERT (max_size > 0,"max size must be > 0");
1120 dxJointGroup *group = new dxJointGroup;
1121 group->num = 0;
1122 return group;
1123}
1124
1125
1126void dJointGroupDestroy (dJointGroupID group)
1127{
1128 dAASSERT (group);
1129 dJointGroupEmpty (group);
1130 delete group;
1131}
1132
1133
1134void dJointGroupEmpty (dJointGroupID group)
1135{
1136 // the joints in this group are detached starting from the most recently
1137 // added (at the top of the stack). this helps ensure that the various
1138 // linked lists are not traversed too much, as the joints will hopefully
1139 // be at the start of those lists.
1140 // if any group joints have their world pointer set to 0, their world was
1141 // previously destroyed. no special handling is required for these joints.
1142
1143 dAASSERT (group);
1144 int i;
1145 dxJoint **jlist = (dxJoint**) ALLOCA (group->num * sizeof(dxJoint*));
1146 dxJoint *j = (dxJoint*) group->stack.rewind();
1147 for (i=0; i < group->num; i++) {
1148 jlist[i] = j;
1149 j = (dxJoint*) (group->stack.next (j->vtable->size));
1150 }
1151 for (i=group->num-1; i >= 0; i--) {
1152 if (jlist[i]->world) {
1153 removeJointReferencesFromAttachedBodies (jlist[i]);
1154 removeObjectFromList (jlist[i]);
1155 jlist[i]->world->nj--;
1156 }
1157 }
1158 group->num = 0;
1159 group->stack.freeAll();
1160}
1161
1162
1163void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2)
1164{
1165 // check arguments
1166 dUASSERT (joint,"bad joint argument");
1167 dUASSERT (body1 == 0 || body1 != body2,"can't have body1==body2");
1168 dxWorld *world = joint->world;
1169 dUASSERT ( (!body1 || body1->world == world) &&
1170 (!body2 || body2->world == world),
1171 "joint and bodies must be in same world");
1172
1173 // check if the joint can not be attached to just one body
1174 dUASSERT (!((joint->flags & dJOINT_TWOBODIES) &&
1175 ((body1 != 0) ^ (body2 != 0))),
1176 "joint can not be attached to just one body");
1177
1178 // remove any existing body attachments
1179 if (joint->node[0].body || joint->node[1].body) {
1180 removeJointReferencesFromAttachedBodies (joint);
1181 }
1182
1183 // if a body is zero, make sure that it is body2, so 0 --> node[1].body
1184 if (body1==0) {
1185 body1 = body2;
1186 body2 = 0;
1187 joint->flags |= dJOINT_REVERSE;
1188 }
1189 else {
1190 joint->flags &= (~dJOINT_REVERSE);
1191 }
1192
1193 // attach to new bodies
1194 joint->node[0].body = body1;
1195 joint->node[1].body = body2;
1196 if (body1) {
1197 joint->node[1].next = body1->firstjoint;
1198 body1->firstjoint = &joint->node[1];
1199 }
1200 else joint->node[1].next = 0;
1201 if (body2) {
1202 joint->node[0].next = body2->firstjoint;
1203 body2->firstjoint = &joint->node[0];
1204 }
1205 else {
1206 joint->node[0].next = 0;
1207 }
1208}
1209
1210
1211void dJointSetData (dxJoint *joint, void *data)
1212{
1213 dAASSERT (joint);
1214 joint->userdata = data;
1215}
1216
1217
1218void *dJointGetData (dxJoint *joint)
1219{
1220 dAASSERT (joint);
1221 return joint->userdata;
1222}
1223
1224
1225int dJointGetType (dxJoint *joint)
1226{
1227 dAASSERT (joint);
1228 return joint->vtable->typenum;
1229}
1230
1231
1232dBodyID dJointGetBody (dxJoint *joint, int index)
1233{
1234 dAASSERT (joint);
1235 if (index == 0 || index == 1) {
1236 if (joint->flags & dJOINT_REVERSE) return joint->node[1-index].body;
1237 else return joint->node[index].body;
1238 }
1239 else return 0;
1240}
1241
1242
1243void dJointSetFeedback (dxJoint *joint, dJointFeedback *f)
1244{
1245 dAASSERT (joint);
1246 joint->feedback = f;
1247}
1248
1249
1250dJointFeedback *dJointGetFeedback (dxJoint *joint)
1251{
1252 dAASSERT (joint);
1253 return joint->feedback;
1254}
1255
1256
1257
1258dJointID dConnectingJoint (dBodyID in_b1, dBodyID in_b2)
1259{
1260 dAASSERT (in_b1 || in_b2);
1261
1262 dBodyID b1, b2;
1263
1264 if (in_b1 == 0) {
1265 b1 = in_b2;
1266 b2 = in_b1;
1267 }
1268 else {
1269 b1 = in_b1;
1270 b2 = in_b2;
1271 }
1272
1273 // look through b1's neighbour list for b2
1274 for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
1275 if (n->body == b2) return n->joint;
1276 }
1277
1278 return 0;
1279}
1280
1281
1282
1283int dConnectingJointList (dBodyID in_b1, dBodyID in_b2, dJointID* out_list)
1284{
1285 dAASSERT (in_b1 || in_b2);
1286
1287
1288 dBodyID b1, b2;
1289
1290 if (in_b1 == 0) {
1291 b1 = in_b2;
1292 b2 = in_b1;
1293 }
1294 else {
1295 b1 = in_b1;
1296 b2 = in_b2;
1297 }
1298
1299 // look through b1's neighbour list for b2
1300 int numConnectingJoints = 0;
1301 for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
1302 if (n->body == b2)
1303 out_list[numConnectingJoints++] = n->joint;
1304 }
1305
1306 return numConnectingJoints;
1307}
1308
1309
1310int dAreConnected (dBodyID b1, dBodyID b2)
1311{
1312 dAASSERT (b1 && b2);
1313 // look through b1's neighbour list for b2
1314 for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
1315 if (n->body == b2) return 1;
1316 }
1317 return 0;
1318}
1319
1320
1321int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type)
1322{
1323 dAASSERT (b1 && b2);
1324 // look through b1's neighbour list for b2
1325 for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
1326 if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1;
1327 }
1328 return 0;
1329}
1330
1331//****************************************************************************
1332// world
1333
1334dxWorld * dWorldCreate()
1335{
1336 dxWorld *w = new dxWorld;
1337 w->firstbody = 0;
1338 w->firstjoint = 0;
1339 w->nb = 0;
1340 w->nj = 0;
1341 dSetZero (w->gravity,4);
1342 w->global_erp = REAL(0.2);
1343#if defined(dSINGLE)
1344 w->global_cfm = 1e-5f;
1345#elif defined(dDOUBLE)
1346 w->global_cfm = 1e-10;
1347#else
1348 #error dSINGLE or dDOUBLE must be defined
1349#endif
1350
1351 w->adis.idle_steps = 10;
1352 w->adis.idle_time = 0;
1353 w->adis_flag = 0;
1354 w->adis.average_samples = 1; // Default is 1 sample => Instantaneous velocity
1355 w->adis.angular_average_threshold = REAL(0.01)*REAL(0.01); // (magnitude squared)
1356 w->adis.linear_average_threshold = REAL(0.01)*REAL(0.01); // (magnitude squared)
1357
1358 w->qs.num_iterations = 20;
1359 w->qs.w = REAL(1.3);
1360
1361 w->contactp.max_vel = dInfinity;
1362 w->contactp.min_depth = 0;
1363
1364 return w;
1365}
1366
1367
1368void dWorldDestroy (dxWorld *w)
1369{
1370 // delete all bodies and joints
1371 dAASSERT (w);
1372 dxBody *nextb, *b = w->firstbody;
1373 while (b) {
1374 nextb = (dxBody*) b->next;
1375 if(b->average_lvel_buffer)
1376 {
1377 delete[] (b->average_lvel_buffer);
1378 b->average_lvel_buffer = 0;
1379 }
1380 if(b->average_avel_buffer)
1381 {
1382 delete[] (b->average_avel_buffer);
1383 b->average_avel_buffer = 0;
1384 }
1385 dBodyDestroy(b); // calling here dBodyDestroy for correct destroying! (i.e. the average buffers)
1386 b = nextb;
1387 }
1388 dxJoint *nextj, *j = w->firstjoint;
1389 while (j) {
1390 nextj = (dxJoint*)j->next;
1391 if (j->flags & dJOINT_INGROUP) {
1392 // the joint is part of a group, so "deactivate" it instead
1393 j->world = 0;
1394 j->node[0].body = 0;
1395 j->node[0].next = 0;
1396 j->node[1].body = 0;
1397 j->node[1].next = 0;
1398 dMessage (0,"warning: destroying world containing grouped joints");
1399 }
1400 else {
1401 dFree (j,j->vtable->size);
1402 }
1403 j = nextj;
1404 }
1405 delete w;
1406}
1407
1408
1409void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z)
1410{
1411 dAASSERT (w);
1412 w->gravity[0] = x;
1413 w->gravity[1] = y;
1414 w->gravity[2] = z;
1415}
1416
1417
1418void dWorldGetGravity (dWorldID w, dVector3 g)
1419{
1420 dAASSERT (w);
1421 g[0] = w->gravity[0];
1422 g[1] = w->gravity[1];
1423 g[2] = w->gravity[2];
1424}
1425
1426
1427void dWorldSetERP (dWorldID w, dReal erp)
1428{
1429 dAASSERT (w);
1430 w->global_erp = erp;
1431}
1432
1433
1434dReal dWorldGetERP (dWorldID w)
1435{
1436 dAASSERT (w);
1437 return w->global_erp;
1438}
1439
1440
1441void dWorldSetCFM (dWorldID w, dReal cfm)
1442{
1443 dAASSERT (w);
1444 w->global_cfm = cfm;
1445}
1446
1447
1448dReal dWorldGetCFM (dWorldID w)
1449{
1450 dAASSERT (w);
1451 return w->global_cfm;
1452}
1453
1454
1455void dWorldStep (dWorldID w, dReal stepsize)
1456{
1457 dUASSERT (w,"bad world argument");
1458 dUASSERT (stepsize > 0,"stepsize must be > 0");
1459 dxProcessIslands (w,stepsize,&dInternalStepIsland);
1460}
1461
1462
1463void dWorldQuickStep (dWorldID w, dReal stepsize)
1464{
1465 dUASSERT (w,"bad world argument");
1466 dUASSERT (stepsize > 0,"stepsize must be > 0");
1467 dxProcessIslands (w,stepsize,&dxQuickStepper);
1468}
1469
1470
1471void dWorldImpulseToForce (dWorldID w, dReal stepsize,
1472 dReal ix, dReal iy, dReal iz,
1473 dVector3 force)
1474{
1475 dAASSERT (w);
1476 stepsize = dRecip(stepsize);
1477 force[0] = stepsize * ix;
1478 force[1] = stepsize * iy;
1479 force[2] = stepsize * iz;
1480 // @@@ force[3] = 0;
1481}
1482
1483
1484// world auto-disable functions
1485
1486dReal dWorldGetAutoDisableLinearThreshold (dWorldID w)
1487{
1488 dAASSERT(w);
1489 return dSqrt (w->adis.linear_average_threshold);
1490}
1491
1492
1493void dWorldSetAutoDisableLinearThreshold (dWorldID w, dReal linear_average_threshold)
1494{
1495 dAASSERT(w);
1496 w->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold;
1497}
1498
1499
1500dReal dWorldGetAutoDisableAngularThreshold (dWorldID w)
1501{
1502 dAASSERT(w);
1503 return dSqrt (w->adis.angular_average_threshold);
1504}
1505
1506
1507void dWorldSetAutoDisableAngularThreshold (dWorldID w, dReal angular_average_threshold)
1508{
1509 dAASSERT(w);
1510 w->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold;
1511}
1512
1513
1514int dWorldGetAutoDisableAverageSamplesCount (dWorldID w)
1515{
1516 dAASSERT(w);
1517 return w->adis.average_samples;
1518}
1519
1520
1521void dWorldSetAutoDisableAverageSamplesCount (dWorldID w, unsigned int average_samples_count)
1522{
1523 dAASSERT(w);
1524 w->adis.average_samples = average_samples_count;
1525}
1526
1527
1528int dWorldGetAutoDisableSteps (dWorldID w)
1529{
1530 dAASSERT(w);
1531 return w->adis.idle_steps;
1532}
1533
1534
1535void dWorldSetAutoDisableSteps (dWorldID w, int steps)
1536{
1537 dAASSERT(w);
1538 w->adis.idle_steps = steps;
1539}
1540
1541
1542dReal dWorldGetAutoDisableTime (dWorldID w)
1543{
1544 dAASSERT(w);
1545 return w->adis.idle_time;
1546}
1547
1548
1549void dWorldSetAutoDisableTime (dWorldID w, dReal time)
1550{
1551 dAASSERT(w);
1552 w->adis.idle_time = time;
1553}
1554
1555
1556int dWorldGetAutoDisableFlag (dWorldID w)
1557{
1558 dAASSERT(w);
1559 return w->adis_flag;
1560}
1561
1562
1563void dWorldSetAutoDisableFlag (dWorldID w, int do_auto_disable)
1564{
1565 dAASSERT(w);
1566 w->adis_flag = (do_auto_disable != 0);
1567}
1568
1569
1570void dWorldSetQuickStepNumIterations (dWorldID w, int num)
1571{
1572 dAASSERT(w);
1573 w->qs.num_iterations = num;
1574}
1575
1576
1577int dWorldGetQuickStepNumIterations (dWorldID w)
1578{
1579 dAASSERT(w);
1580 return w->qs.num_iterations;
1581}
1582
1583
1584void dWorldSetQuickStepW (dWorldID w, dReal param)
1585{
1586 dAASSERT(w);
1587 w->qs.w = param;
1588}
1589
1590
1591dReal dWorldGetQuickStepW (dWorldID w)
1592{
1593 dAASSERT(w);
1594 return w->qs.w;
1595}
1596
1597
1598void dWorldSetContactMaxCorrectingVel (dWorldID w, dReal vel)
1599{
1600 dAASSERT(w);
1601 w->contactp.max_vel = vel;
1602}
1603
1604
1605dReal dWorldGetContactMaxCorrectingVel (dWorldID w)
1606{
1607 dAASSERT(w);
1608 return w->contactp.max_vel;
1609}
1610
1611
1612void dWorldSetContactSurfaceLayer (dWorldID w, dReal depth)
1613{
1614 dAASSERT(w);
1615 w->contactp.min_depth = depth;
1616}
1617
1618
1619dReal dWorldGetContactSurfaceLayer (dWorldID w)
1620{
1621 dAASSERT(w);
1622 return w->contactp.min_depth;
1623}
1624
1625//****************************************************************************
1626// testing
1627
1628#define NUM 100
1629
1630#define DO(x)
1631
1632
1633extern "C" void dTestDataStructures()
1634{
1635 int i;
1636 DO(printf ("testDynamicsStuff()\n"));
1637
1638 dBodyID body [NUM];
1639 int nb = 0;
1640 dJointID joint [NUM];
1641 int nj = 0;
1642
1643 for (i=0; i<NUM; i++) body[i] = 0;
1644 for (i=0; i<NUM; i++) joint[i] = 0;
1645
1646 DO(printf ("creating world\n"));
1647 dWorldID w = dWorldCreate();
1648 checkWorld (w);
1649
1650 for (;;) {
1651 if (nb < NUM && dRandReal() > 0.5) {
1652 DO(printf ("creating body\n"));
1653 body[nb] = dBodyCreate (w);
1654 DO(printf ("\t--> %p\n",body[nb]));
1655 nb++;
1656 checkWorld (w);
1657 DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
1658 }
1659 if (nj < NUM && nb > 2 && dRandReal() > 0.5) {
1660 dBodyID b1 = body [dRand() % nb];
1661 dBodyID b2 = body [dRand() % nb];
1662 if (b1 != b2) {
1663 DO(printf ("creating joint, attaching to %p,%p\n",b1,b2));
1664 joint[nj] = dJointCreateBall (w,0);
1665 DO(printf ("\t-->%p\n",joint[nj]));
1666 checkWorld (w);
1667 dJointAttach (joint[nj],b1,b2);
1668 nj++;
1669 checkWorld (w);
1670 DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
1671 }
1672 }
1673 if (nj > 0 && nb > 2 && dRandReal() > 0.5) {
1674 dBodyID b1 = body [dRand() % nb];
1675 dBodyID b2 = body [dRand() % nb];
1676 if (b1 != b2) {
1677 int k = dRand() % nj;
1678 DO(printf ("reattaching joint %p\n",joint[k]));
1679 dJointAttach (joint[k],b1,b2);
1680 checkWorld (w);
1681 DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
1682 }
1683 }
1684 if (nb > 0 && dRandReal() > 0.5) {
1685 int k = dRand() % nb;
1686 DO(printf ("destroying body %p\n",body[k]));
1687 dBodyDestroy (body[k]);
1688 checkWorld (w);
1689 for (; k < (NUM-1); k++) body[k] = body[k+1];
1690 nb--;
1691 DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
1692 }
1693 if (nj > 0 && dRandReal() > 0.5) {
1694 int k = dRand() % nj;
1695 DO(printf ("destroying joint %p\n",joint[k]));
1696 dJointDestroy (joint[k]);
1697 checkWorld (w);
1698 for (; k < (NUM-1); k++) joint[k] = joint[k+1];
1699 nj--;
1700 DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
1701 }
1702 }
1703
1704 /*
1705 printf ("creating world\n");
1706 dWorldID w = dWorldCreate();
1707 checkWorld (w);
1708 printf ("creating body\n");
1709 dBodyID b1 = dBodyCreate (w);
1710 checkWorld (w);
1711 printf ("creating body\n");
1712 dBodyID b2 = dBodyCreate (w);
1713 checkWorld (w);
1714 printf ("creating joint\n");
1715 dJointID j = dJointCreateBall (w);
1716 checkWorld (w);
1717 printf ("attaching joint\n");
1718 dJointAttach (j,b1,b2);
1719 checkWorld (w);
1720 printf ("destroying joint\n");
1721 dJointDestroy (j);
1722 checkWorld (w);
1723 printf ("destroying body\n");
1724 dBodyDestroy (b1);
1725 checkWorld (w);
1726 printf ("destroying body\n");
1727 dBodyDestroy (b2);
1728 checkWorld (w);
1729 printf ("destroying world\n");
1730 dWorldDestroy (w);
1731 */
1732}
diff --git a/libraries/ode-0.9/ode/src/odemath.cpp b/libraries/ode-0.9/ode/src/odemath.cpp
deleted file mode 100644
index 11bc84e..0000000
--- a/libraries/ode-0.9/ode/src/odemath.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/common.h>
24#include <ode/odemath.h>
25
26// get some math functions under windows
27#ifdef WIN32
28#include <float.h>
29#ifndef CYGWIN // added by andy for cygwin
30#undef copysign
31#define copysign(a,b) ((dReal)_copysign(a,b))
32#endif // added by andy for cygwin
33#endif
34
35#undef dNormalize3
36#undef dNormalize4
37
38
39// this may be called for vectors `a' with extremely small magnitude, for
40// example the result of a cross product on two nearly perpendicular vectors.
41// we must be robust to these small vectors. to prevent numerical error,
42// first find the component a[i] with the largest magnitude and then scale
43// all the components by 1/a[i]. then we can compute the length of `a' and
44// scale the components by 1/l. this has been verified to work with vectors
45// containing the smallest representable numbers.
46
47int dSafeNormalize3 (dVector3 a)
48{
49 dReal a0,a1,a2,aa0,aa1,aa2,l;
50 dAASSERT (a);
51 a0 = a[0];
52 a1 = a[1];
53 a2 = a[2];
54 aa0 = dFabs(a0);
55 aa1 = dFabs(a1);
56 aa2 = dFabs(a2);
57 if (aa1 > aa0) {
58 if (aa2 > aa1) {
59 goto aa2_largest;
60 }
61 else { // aa1 is largest
62 a0 /= aa1;
63 a2 /= aa1;
64 l = dRecipSqrt (a0*a0 + a2*a2 + 1);
65 a[0] = a0*l;
66 a[1] = dCopySign(l,a1);
67 a[2] = a2*l;
68 }
69 }
70 else {
71 if (aa2 > aa0) {
72 aa2_largest: // aa2 is largest
73 a0 /= aa2;
74 a1 /= aa2;
75 l = dRecipSqrt (a0*a0 + a1*a1 + 1);
76 a[0] = a0*l;
77 a[1] = a1*l;
78 a[2] = dCopySign(l,a2);
79 }
80 else { // aa0 is largest
81 if (aa0 <= 0) {
82 a[0] = 1; // if all a's are zero, this is where we'll end up.
83 a[1] = 0; // return a default unit length vector.
84 a[2] = 0;
85 return 0;
86 }
87 a1 /= aa0;
88 a2 /= aa0;
89 l = dRecipSqrt (a1*a1 + a2*a2 + 1);
90 a[0] = dCopySign(l,a0);
91 a[1] = a1*l;
92 a[2] = a2*l;
93 }
94 }
95 return 1;
96}
97
98/* OLD VERSION */
99/*
100void dNormalize3 (dVector3 a)
101{
102 dIASSERT (a);
103 dReal l = dDOT(a,a);
104 if (l > 0) {
105 l = dRecipSqrt(l);
106 a[0] *= l;
107 a[1] *= l;
108 a[2] *= l;
109 }
110 else {
111 a[0] = 1;
112 a[1] = 0;
113 a[2] = 0;
114 }
115}
116*/
117
118void dNormalize3(dVector3 a)
119{
120 _dNormalize3(a);
121}
122
123
124int dSafeNormalize4 (dVector4 a)
125{
126 dAASSERT (a);
127 dReal l = dDOT(a,a)+a[3]*a[3];
128 if (l > 0) {
129 l = dRecipSqrt(l);
130 a[0] *= l;
131 a[1] *= l;
132 a[2] *= l;
133 a[3] *= l;
134 return 1;
135 }
136 else {
137 a[0] = 1;
138 a[1] = 0;
139 a[2] = 0;
140 a[3] = 0;
141 return 0;
142 }
143}
144
145void dNormalize4(dVector4 a)
146{
147 _dNormalize4(a);
148}
149
150
151void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q)
152{
153 dAASSERT (n && p && q);
154 if (dFabs(n[2]) > M_SQRT1_2) {
155 // choose p in y-z plane
156 dReal a = n[1]*n[1] + n[2]*n[2];
157 dReal k = dRecipSqrt (a);
158 p[0] = 0;
159 p[1] = -n[2]*k;
160 p[2] = n[1]*k;
161 // set q = n x p
162 q[0] = a*k;
163 q[1] = -n[0]*p[2];
164 q[2] = n[0]*p[1];
165 }
166 else {
167 // choose p in x-y plane
168 dReal a = n[0]*n[0] + n[1]*n[1];
169 dReal k = dRecipSqrt (a);
170 p[0] = -n[1]*k;
171 p[1] = n[0]*k;
172 p[2] = 0;
173 // set q = n x p
174 q[0] = -n[2]*p[1];
175 q[1] = n[2]*p[0];
176 q[2] = a*k;
177 }
178}
diff --git a/libraries/ode-0.9/ode/src/plane.cpp b/libraries/ode-0.9/ode/src/plane.cpp
deleted file mode 100644
index e3afb49..0000000
--- a/libraries/ode-0.9/ode/src/plane.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45//****************************************************************************
46// plane public API
47
48static void make_sure_plane_normal_has_unit_length (dxPlane *g)
49{
50 dReal l = g->p[0]*g->p[0] + g->p[1]*g->p[1] + g->p[2]*g->p[2];
51 if (l > 0) {
52 l = dRecipSqrt(l);
53 g->p[0] *= l;
54 g->p[1] *= l;
55 g->p[2] *= l;
56 g->p[3] *= l;
57 }
58 else {
59 g->p[0] = 1;
60 g->p[1] = 0;
61 g->p[2] = 0;
62 g->p[3] = 0;
63 }
64}
65
66
67dxPlane::dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d) :
68 dxGeom (space,0)
69{
70 type = dPlaneClass;
71 p[0] = a;
72 p[1] = b;
73 p[2] = c;
74 p[3] = d;
75 make_sure_plane_normal_has_unit_length (this);
76}
77
78
79void dxPlane::computeAABB()
80{
81 aabb[0] = -dInfinity;
82 aabb[1] = dInfinity;
83 aabb[2] = -dInfinity;
84 aabb[3] = dInfinity;
85 aabb[4] = -dInfinity;
86 aabb[5] = dInfinity;
87
88 // Planes that have normal vectors aligned along an axis can use a
89 // less comprehensive (half space) bounding box.
90
91 if ( p[1] == 0.0f && p[2] == 0.0f ) {
92 // normal aligned with x-axis
93 aabb[0] = (p[0] > 0) ? -dInfinity : -p[3];
94 aabb[1] = (p[0] > 0) ? p[3] : dInfinity;
95 } else
96 if ( p[0] == 0.0f && p[2] == 0.0f ) {
97 // normal aligned with y-axis
98 aabb[2] = (p[1] > 0) ? -dInfinity : -p[3];
99 aabb[3] = (p[1] > 0) ? p[3] : dInfinity;
100 } else
101 if ( p[0] == 0.0f && p[1] == 0.0f ) {
102 // normal aligned with z-axis
103 aabb[4] = (p[2] > 0) ? -dInfinity : -p[3];
104 aabb[5] = (p[2] > 0) ? p[3] : dInfinity;
105 }
106}
107
108
109dGeomID dCreatePlane (dSpaceID space,
110 dReal a, dReal b, dReal c, dReal d)
111{
112 return new dxPlane (space,a,b,c,d);
113}
114
115
116void dGeomPlaneSetParams (dGeomID g, dReal a, dReal b, dReal c, dReal d)
117{
118 dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
119 dxPlane *p = (dxPlane*) g;
120 p->p[0] = a;
121 p->p[1] = b;
122 p->p[2] = c;
123 p->p[3] = d;
124 make_sure_plane_normal_has_unit_length (p);
125 dGeomMoved (g);
126}
127
128
129void dGeomPlaneGetParams (dGeomID g, dVector4 result)
130{
131 dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
132 dxPlane *p = (dxPlane*) g;
133 result[0] = p->p[0];
134 result[1] = p->p[1];
135 result[2] = p->p[2];
136 result[3] = p->p[3];
137}
138
139
140dReal dGeomPlanePointDepth (dGeomID g, dReal x, dReal y, dReal z)
141{
142 dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
143 dxPlane *p = (dxPlane*) g;
144 return p->p[3] - p->p[0]*x - p->p[1]*y - p->p[2]*z;
145}
diff --git a/libraries/ode-0.9/ode/src/quickstep.cpp b/libraries/ode-0.9/ode/src/quickstep.cpp
deleted file mode 100644
index 07aa9f7..0000000
--- a/libraries/ode-0.9/ode/src/quickstep.cpp
+++ /dev/null
@@ -1,880 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include "objects.h"
24#include "joint.h"
25#include <ode/config.h>
26#include <ode/odemath.h>
27#include <ode/rotation.h>
28#include <ode/timer.h>
29#include <ode/error.h>
30#include <ode/matrix.h>
31#include <ode/misc.h>
32#include "lcp.h"
33#include "util.h"
34
35#define ALLOCA dALLOCA16
36
37typedef const dReal *dRealPtr;
38typedef dReal *dRealMutablePtr;
39#define dRealArray(name,n) dReal name[n];
40#define dRealAllocaArray(name,n) dReal *name = (dReal*) ALLOCA ((n)*sizeof(dReal));
41
42//***************************************************************************
43// configuration
44
45// for the SOR and CG methods:
46// uncomment the following line to use warm starting. this definitely
47// help for motor-driven joints. unfortunately it appears to hurt
48// with high-friction contacts using the SOR method. use with care
49
50//#define WARM_STARTING 1
51
52
53// for the SOR method:
54// uncomment the following line to determine a new constraint-solving
55// order for each iteration. however, the qsort per iteration is expensive,
56// and the optimal order is somewhat problem dependent.
57// @@@ try the leaf->root ordering.
58
59//#define REORDER_CONSTRAINTS 1
60
61
62// for the SOR method:
63// uncomment the following line to randomly reorder constraint rows
64// during the solution. depending on the situation, this can help a lot
65// or hardly at all, but it doesn't seem to hurt.
66
67#define RANDOMLY_REORDER_CONSTRAINTS 1
68
69//****************************************************************************
70// special matrix multipliers
71
72// multiply block of B matrix (q x 6) with 12 dReal per row with C vektor (q)
73static void Multiply1_12q1 (dReal *A, dReal *B, dReal *C, int q)
74{
75 int k;
76 dReal sum;
77 dIASSERT (q>0 && A && B && C);
78 sum = 0;
79 for (k=0; k<q; k++) sum += B[k*12] * C[k];
80 A[0] = sum;
81 sum = 0;
82 for (k=0; k<q; k++) sum += B[1+k*12] * C[k];
83 A[1] = sum;
84 sum = 0;
85 for (k=0; k<q; k++) sum += B[2+k*12] * C[k];
86 A[2] = sum;
87 sum = 0;
88 for (k=0; k<q; k++) sum += B[3+k*12] * C[k];
89 A[3] = sum;
90 sum = 0;
91 for (k=0; k<q; k++) sum += B[4+k*12] * C[k];
92 A[4] = sum;
93 sum = 0;
94 for (k=0; k<q; k++) sum += B[5+k*12] * C[k];
95 A[5] = sum;
96}
97
98//***************************************************************************
99// testing stuff
100
101#ifdef TIMING
102#define IFTIMING(x) x
103#else
104#define IFTIMING(x) /* */
105#endif
106
107//***************************************************************************
108// various common computations involving the matrix J
109
110// compute iMJ = inv(M)*J'
111
112static void compute_invM_JT (int m, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb,
113 dxBody * const *body, dRealPtr invI)
114{
115 int i,j;
116 dRealMutablePtr iMJ_ptr = iMJ;
117 dRealMutablePtr J_ptr = J;
118 for (i=0; i<m; i++) {
119 int b1 = jb[i*2];
120 int b2 = jb[i*2+1];
121 dReal k = body[b1]->invMass;
122 for (j=0; j<3; j++) iMJ_ptr[j] = k*J_ptr[j];
123 dMULTIPLY0_331 (iMJ_ptr + 3, invI + 12*b1, J_ptr + 3);
124 if (b2 >= 0) {
125 k = body[b2]->invMass;
126 for (j=0; j<3; j++) iMJ_ptr[j+6] = k*J_ptr[j+6];
127 dMULTIPLY0_331 (iMJ_ptr + 9, invI + 12*b2, J_ptr + 9);
128 }
129 J_ptr += 12;
130 iMJ_ptr += 12;
131 }
132}
133
134
135// compute out = inv(M)*J'*in.
136
137static void multiply_invM_JT (int m, int nb, dRealMutablePtr iMJ, int *jb,
138 dRealMutablePtr in, dRealMutablePtr out)
139{
140 int i,j;
141 dSetZero (out,6*nb);
142 dRealPtr iMJ_ptr = iMJ;
143 for (i=0; i<m; i++) {
144 int b1 = jb[i*2];
145 int b2 = jb[i*2+1];
146 dRealMutablePtr out_ptr = out + b1*6;
147 for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i];
148 iMJ_ptr += 6;
149 if (b2 >= 0) {
150 out_ptr = out + b2*6;
151 for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i];
152 }
153 iMJ_ptr += 6;
154 }
155}
156
157
158// compute out = J*in.
159
160static void multiply_J (int m, dRealMutablePtr J, int *jb,
161 dRealMutablePtr in, dRealMutablePtr out)
162{
163 int i,j;
164 dRealPtr J_ptr = J;
165 for (i=0; i<m; i++) {
166 int b1 = jb[i*2];
167 int b2 = jb[i*2+1];
168 dReal sum = 0;
169 dRealMutablePtr in_ptr = in + b1*6;
170 for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
171 J_ptr += 6;
172 if (b2 >= 0) {
173 in_ptr = in + b2*6;
174 for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
175 }
176 J_ptr += 6;
177 out[i] = sum;
178 }
179}
180
181
182// compute out = (J*inv(M)*J' + cfm)*in.
183// use z as an nb*6 temporary.
184
185static void multiply_J_invM_JT (int m, int nb, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb,
186 dRealPtr cfm, dRealMutablePtr z, dRealMutablePtr in, dRealMutablePtr out)
187{
188 multiply_invM_JT (m,nb,iMJ,jb,in,z);
189 multiply_J (m,J,jb,z,out);
190
191 // add cfm
192 for (int i=0; i<m; i++) out[i] += cfm[i] * in[i];
193}
194
195//***************************************************************************
196// conjugate gradient method with jacobi preconditioner
197// THIS IS EXPERIMENTAL CODE that doesn't work too well, so it is ifdefed out.
198//
199// adding CFM seems to be critically important to this method.
200
201#if 0
202
203static inline dReal dot (int n, dRealPtr x, dRealPtr y)
204{
205 dReal sum=0;
206 for (int i=0; i<n; i++) sum += x[i]*y[i];
207 return sum;
208}
209
210
211// x = y + z*alpha
212
213static inline void add (int n, dRealMutablePtr x, dRealPtr y, dRealPtr z, dReal alpha)
214{
215 for (int i=0; i<n; i++) x[i] = y[i] + z[i]*alpha;
216}
217
218
219static void CG_LCP (int m, int nb, dRealMutablePtr J, int *jb, dxBody * const *body,
220 dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr fc, dRealMutablePtr b,
221 dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex,
222 dxQuickStepParameters *qs)
223{
224 int i,j;
225 const int num_iterations = qs->num_iterations;
226
227 // precompute iMJ = inv(M)*J'
228 dRealAllocaArray (iMJ,m*12);
229 compute_invM_JT (m,J,iMJ,jb,body,invI);
230
231 dReal last_rho = 0;
232 dRealAllocaArray (r,m);
233 dRealAllocaArray (z,m);
234 dRealAllocaArray (p,m);
235 dRealAllocaArray (q,m);
236
237 // precompute 1 / diagonals of A
238 dRealAllocaArray (Ad,m);
239 dRealPtr iMJ_ptr = iMJ;
240 dRealPtr J_ptr = J;
241 for (i=0; i<m; i++) {
242 dReal sum = 0;
243 for (j=0; j<6; j++) sum += iMJ_ptr[j] * J_ptr[j];
244 if (jb[i*2+1] >= 0) {
245 for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j];
246 }
247 iMJ_ptr += 12;
248 J_ptr += 12;
249 Ad[i] = REAL(1.0) / (sum + cfm[i]);
250 }
251
252#ifdef WARM_STARTING
253 // compute residual r = b - A*lambda
254 multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,lambda,r);
255 for (i=0; i<m; i++) r[i] = b[i] - r[i];
256#else
257 dSetZero (lambda,m);
258 memcpy (r,b,m*sizeof(dReal)); // residual r = b - A*lambda
259#endif
260
261 for (int iteration=0; iteration < num_iterations; iteration++) {
262 for (i=0; i<m; i++) z[i] = r[i]*Ad[i]; // z = inv(M)*r
263 dReal rho = dot (m,r,z); // rho = r'*z
264
265 // @@@
266 // we must check for convergence, otherwise rho will go to 0 if
267 // we get an exact solution, which will introduce NaNs into the equations.
268 if (rho < 1e-10) {
269 printf ("CG returned at iteration %d\n",iteration);
270 break;
271 }
272
273 if (iteration==0) {
274 memcpy (p,z,m*sizeof(dReal)); // p = z
275 }
276 else {
277 add (m,p,z,p,rho/last_rho); // p = z + (rho/last_rho)*p
278 }
279
280 // compute q = (J*inv(M)*J')*p
281 multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,p,q);
282
283 dReal alpha = rho/dot (m,p,q); // alpha = rho/(p'*q)
284 add (m,lambda,lambda,p,alpha); // lambda = lambda + alpha*p
285 add (m,r,r,q,-alpha); // r = r - alpha*q
286 last_rho = rho;
287 }
288
289 // compute fc = inv(M)*J'*lambda
290 multiply_invM_JT (m,nb,iMJ,jb,lambda,fc);
291
292#if 0
293 // measure solution error
294 multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,lambda,r);
295 dReal error = 0;
296 for (i=0; i<m; i++) error += dFabs(r[i] - b[i]);
297 printf ("lambda error = %10.6e\n",error);
298#endif
299}
300
301#endif
302
303//***************************************************************************
304// SOR-LCP method
305
306// nb is the number of bodies in the body array.
307// J is an m*12 matrix of constraint rows
308// jb is an array of first and second body numbers for each constraint row
309// invI is the global frame inverse inertia for each body (stacked 3x3 matrices)
310//
311// this returns lambda and fc (the constraint force).
312// note: fc is returned as inv(M)*J'*lambda, the constraint force is actually J'*lambda
313//
314// b, lo and hi are modified on exit
315
316
317struct IndexError {
318 dReal error; // error to sort on
319 int findex;
320 int index; // row index
321};
322
323
324#ifdef REORDER_CONSTRAINTS
325
326static int compare_index_error (const void *a, const void *b)
327{
328 const IndexError *i1 = (IndexError*) a;
329 const IndexError *i2 = (IndexError*) b;
330 if (i1->findex < 0 && i2->findex >= 0) return -1;
331 if (i1->findex >= 0 && i2->findex < 0) return 1;
332 if (i1->error < i2->error) return -1;
333 if (i1->error > i2->error) return 1;
334 return 0;
335}
336
337#endif
338
339
340static void SOR_LCP (int m, int nb, dRealMutablePtr J, int *jb, dxBody * const *body,
341 dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr fc, dRealMutablePtr b,
342 dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex,
343 dxQuickStepParameters *qs)
344{
345 const int num_iterations = qs->num_iterations;
346 const dReal sor_w = qs->w; // SOR over-relaxation parameter
347
348 int i,j;
349
350#ifdef WARM_STARTING
351 // for warm starting, this seems to be necessary to prevent
352 // jerkiness in motor-driven joints. i have no idea why this works.
353 for (i=0; i<m; i++) lambda[i] *= 0.9;
354#else
355 dSetZero (lambda,m);
356#endif
357
358#ifdef REORDER_CONSTRAINTS
359 // the lambda computed at the previous iteration.
360 // this is used to measure error for when we are reordering the indexes.
361 dRealAllocaArray (last_lambda,m);
362#endif
363
364 // a copy of the 'hi' vector in case findex[] is being used
365 dRealAllocaArray (hicopy,m);
366 memcpy (hicopy,hi,m*sizeof(dReal));
367
368 // precompute iMJ = inv(M)*J'
369 dRealAllocaArray (iMJ,m*12);
370 compute_invM_JT (m,J,iMJ,jb,body,invI);
371
372 // compute fc=(inv(M)*J')*lambda. we will incrementally maintain fc
373 // as we change lambda.
374#ifdef WARM_STARTING
375 multiply_invM_JT (m,nb,iMJ,jb,lambda,fc);
376#else
377 dSetZero (fc,nb*6);
378#endif
379
380 // precompute 1 / diagonals of A
381 dRealAllocaArray (Ad,m);
382 dRealPtr iMJ_ptr = iMJ;
383 dRealMutablePtr J_ptr = J;
384 for (i=0; i<m; i++) {
385 dReal sum = 0;
386 for (j=0; j<6; j++) sum += iMJ_ptr[j] * J_ptr[j];
387 if (jb[i*2+1] >= 0) {
388 for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j];
389 }
390 iMJ_ptr += 12;
391 J_ptr += 12;
392 Ad[i] = sor_w / (sum + cfm[i]);
393 }
394
395 // scale J and b by Ad
396 J_ptr = J;
397 for (i=0; i<m; i++) {
398 for (j=0; j<12; j++) {
399 J_ptr[0] *= Ad[i];
400 J_ptr++;
401 }
402 b[i] *= Ad[i];
403
404 // scale Ad by CFM. N.B. this should be done last since it is used above
405 Ad[i] *= cfm[i];
406 }
407
408 // order to solve constraint rows in
409 IndexError *order = (IndexError*) ALLOCA (m*sizeof(IndexError));
410
411#ifndef REORDER_CONSTRAINTS
412 // make sure constraints with findex < 0 come first.
413 j=0;
414 int k=1;
415
416 // Fill the array from both ends
417 for (i=0; i<m; i++)
418 if (findex[i] < 0)
419 order[j++].index = i; // Place them at the front
420 else
421 order[m-k++].index = i; // Place them at the end
422
423 dIASSERT ((j+k-1)==m); // -1 since k was started at 1 and not 0
424#endif
425
426 for (int iteration=0; iteration < num_iterations; iteration++) {
427
428#ifdef REORDER_CONSTRAINTS
429 // constraints with findex < 0 always come first.
430 if (iteration < 2) {
431 // for the first two iterations, solve the constraints in
432 // the given order
433 for (i=0; i<m; i++) {
434 order[i].error = i;
435 order[i].findex = findex[i];
436 order[i].index = i;
437 }
438 }
439 else {
440 // sort the constraints so that the ones converging slowest
441 // get solved last. use the absolute (not relative) error.
442 for (i=0; i<m; i++) {
443 dReal v1 = dFabs (lambda[i]);
444 dReal v2 = dFabs (last_lambda[i]);
445 dReal max = (v1 > v2) ? v1 : v2;
446 if (max > 0) {
447 //@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max;
448 order[i].error = dFabs(lambda[i]-last_lambda[i]);
449 }
450 else {
451 order[i].error = dInfinity;
452 }
453 order[i].findex = findex[i];
454 order[i].index = i;
455 }
456 }
457 qsort (order,m,sizeof(IndexError),&compare_index_error);
458
459 //@@@ potential optimization: swap lambda and last_lambda pointers rather
460 // than copying the data. we must make sure lambda is properly
461 // returned to the caller
462 memcpy (last_lambda,lambda,m*sizeof(dReal));
463#endif
464#ifdef RANDOMLY_REORDER_CONSTRAINTS
465 if ((iteration & 7) == 0) {
466 for (i=1; i<m; ++i) {
467 IndexError tmp = order[i];
468 int swapi = dRandInt(i+1);
469 order[i] = order[swapi];
470 order[swapi] = tmp;
471 }
472 }
473#endif
474
475 for (int i=0; i<m; i++) {
476 // @@@ potential optimization: we could pre-sort J and iMJ, thereby
477 // linearizing access to those arrays. hmmm, this does not seem
478 // like a win, but we should think carefully about our memory
479 // access pattern.
480
481 int index = order[i].index;
482 J_ptr = J + index*12;
483 iMJ_ptr = iMJ + index*12;
484
485 // set the limits for this constraint. note that 'hicopy' is used.
486 // this is the place where the QuickStep method differs from the
487 // direct LCP solving method, since that method only performs this
488 // limit adjustment once per time step, whereas this method performs
489 // once per iteration per constraint row.
490 // the constraints are ordered so that all lambda[] values needed have
491 // already been computed.
492 if (findex[index] >= 0) {
493 hi[index] = dFabs (hicopy[index] * lambda[findex[index]]);
494 lo[index] = -hi[index];
495 }
496
497 int b1 = jb[index*2];
498 int b2 = jb[index*2+1];
499 dReal delta = b[index] - lambda[index]*Ad[index];
500 dRealMutablePtr fc_ptr = fc + 6*b1;
501
502 // @@@ potential optimization: SIMD-ize this and the b2 >= 0 case
503 delta -=fc_ptr[0] * J_ptr[0] + fc_ptr[1] * J_ptr[1] +
504 fc_ptr[2] * J_ptr[2] + fc_ptr[3] * J_ptr[3] +
505 fc_ptr[4] * J_ptr[4] + fc_ptr[5] * J_ptr[5];
506 // @@@ potential optimization: handle 1-body constraints in a separate
507 // loop to avoid the cost of test & jump?
508 if (b2 >= 0) {
509 fc_ptr = fc + 6*b2;
510 delta -=fc_ptr[0] * J_ptr[6] + fc_ptr[1] * J_ptr[7] +
511 fc_ptr[2] * J_ptr[8] + fc_ptr[3] * J_ptr[9] +
512 fc_ptr[4] * J_ptr[10] + fc_ptr[5] * J_ptr[11];
513 }
514
515 // compute lambda and clamp it to [lo,hi].
516 // @@@ potential optimization: does SSE have clamping instructions
517 // to save test+jump penalties here?
518 dReal new_lambda = lambda[index] + delta;
519 if (new_lambda < lo[index]) {
520 delta = lo[index]-lambda[index];
521 lambda[index] = lo[index];
522 }
523 else if (new_lambda > hi[index]) {
524 delta = hi[index]-lambda[index];
525 lambda[index] = hi[index];
526 }
527 else {
528 lambda[index] = new_lambda;
529 }
530
531 //@@@ a trick that may or may not help
532 //dReal ramp = (1-((dReal)(iteration+1)/(dReal)num_iterations));
533 //delta *= ramp;
534
535 // update fc.
536 // @@@ potential optimization: SIMD for this and the b2 >= 0 case
537 fc_ptr = fc + 6*b1;
538 fc_ptr[0] += delta * iMJ_ptr[0];
539 fc_ptr[1] += delta * iMJ_ptr[1];
540 fc_ptr[2] += delta * iMJ_ptr[2];
541 fc_ptr[3] += delta * iMJ_ptr[3];
542 fc_ptr[4] += delta * iMJ_ptr[4];
543 fc_ptr[5] += delta * iMJ_ptr[5];
544 // @@@ potential optimization: handle 1-body constraints in a separate
545 // loop to avoid the cost of test & jump?
546 if (b2 >= 0) {
547 fc_ptr = fc + 6*b2;
548 fc_ptr[0] += delta * iMJ_ptr[6];
549 fc_ptr[1] += delta * iMJ_ptr[7];
550 fc_ptr[2] += delta * iMJ_ptr[8];
551 fc_ptr[3] += delta * iMJ_ptr[9];
552 fc_ptr[4] += delta * iMJ_ptr[10];
553 fc_ptr[5] += delta * iMJ_ptr[11];
554 }
555 }
556 }
557}
558
559
560void dxQuickStepper (dxWorld *world, dxBody * const *body, int nb,
561 dxJoint * const *_joint, int nj, dReal stepsize)
562{
563 int i,j;
564 IFTIMING(dTimerStart("preprocessing");)
565
566 dReal stepsize1 = dRecip(stepsize);
567
568 // number all bodies in the body list - set their tag values
569 for (i=0; i<nb; i++) body[i]->tag = i;
570
571 // make a local copy of the joint array, because we might want to modify it.
572 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
573 // but not the joint array, because the caller might need it unchanged).
574 //@@@ do we really need to do this? we'll be sorting constraint rows individually, not joints
575 dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*));
576 memcpy (joint,_joint,nj * sizeof(dxJoint*));
577
578 // for all bodies, compute the inertia tensor and its inverse in the global
579 // frame, and compute the rotational force and add it to the torque
580 // accumulator. I and invI are a vertical stack of 3x4 matrices, one per body.
581 //dRealAllocaArray (I,3*4*nb); // need to remember all I's for feedback purposes only
582 dRealAllocaArray (invI,3*4*nb);
583 for (i=0; i<nb; i++) {
584 dMatrix3 tmp;
585
586 // compute inverse inertia tensor in global frame
587 dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
588 dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
589#ifdef dGYROSCOPIC
590 dMatrix3 I;
591 // compute inertia tensor in global frame
592 dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
593 //dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
594 dMULTIPLY0_333 (I,body[i]->posr.R,tmp);
595 // compute rotational force
596 //dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
597 dMULTIPLY0_331 (tmp,I,body[i]->avel);
598 dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
599#endif
600 }
601
602 // add the gravity force to all bodies
603 for (i=0; i<nb; i++) {
604 if ((body[i]->flags & dxBodyNoGravity)==0) {
605 body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
606 body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
607 body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
608 }
609 }
610
611 // get joint information (m = total constraint dimension, nub = number of unbounded variables).
612 // joints with m=0 are inactive and are removed from the joints array
613 // entirely, so that the code that follows does not consider them.
614 //@@@ do we really need to save all the info1's
615 dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1));
616 for (i=0, j=0; j<nj; j++) { // i=dest, j=src
617 joint[j]->vtable->getInfo1 (joint[j],info+i);
618 dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
619 if (info[i].m > 0) {
620 joint[i] = joint[j];
621 i++;
622 }
623 }
624 nj = i;
625
626 // create the row offset array
627 int m = 0;
628 int *ofs = (int*) ALLOCA (nj*sizeof(int));
629 for (i=0; i<nj; i++) {
630 ofs[i] = m;
631 m += info[i].m;
632 }
633
634 // if there are constraints, compute the constraint force
635 dRealAllocaArray (J,m*12);
636 int *jb = (int*) ALLOCA (m*2*sizeof(int));
637 if (m > 0) {
638 // create a constraint equation right hand side vector `c', a constraint
639 // force mixing vector `cfm', and LCP low and high bound vectors, and an
640 // 'findex' vector.
641 dRealAllocaArray (c,m);
642 dRealAllocaArray (cfm,m);
643 dRealAllocaArray (lo,m);
644 dRealAllocaArray (hi,m);
645 int *findex = (int*) ALLOCA (m*sizeof(int));
646 dSetZero (c,m);
647 dSetValue (cfm,m,world->global_cfm);
648 dSetValue (lo,m,-dInfinity);
649 dSetValue (hi,m, dInfinity);
650 for (i=0; i<m; i++) findex[i] = -1;
651
652 // get jacobian data from constraints. an m*12 matrix will be created
653 // to store the two jacobian blocks from each constraint. it has this
654 // format:
655 //
656 // l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 \ .
657 // l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 }-- jacobian for joint 0, body 1 and body 2 (3 rows)
658 // l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 /
659 // l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 }--- jacobian for joint 1, body 1 and body 2 (3 rows)
660 // etc...
661 //
662 // (lll) = linear jacobian data
663 // (aaa) = angular jacobian data
664 //
665 IFTIMING (dTimerNow ("create J");)
666 dSetZero (J,m*12);
667 dxJoint::Info2 Jinfo;
668 Jinfo.rowskip = 12;
669 Jinfo.fps = stepsize1;
670 Jinfo.erp = world->global_erp;
671 int mfb = 0; // number of rows of Jacobian we will have to save for joint feedback
672 for (i=0; i<nj; i++) {
673 Jinfo.J1l = J + ofs[i]*12;
674 Jinfo.J1a = Jinfo.J1l + 3;
675 Jinfo.J2l = Jinfo.J1l + 6;
676 Jinfo.J2a = Jinfo.J1l + 9;
677 Jinfo.c = c + ofs[i];
678 Jinfo.cfm = cfm + ofs[i];
679 Jinfo.lo = lo + ofs[i];
680 Jinfo.hi = hi + ofs[i];
681 Jinfo.findex = findex + ofs[i];
682 joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
683 // adjust returned findex values for global index numbering
684 for (j=0; j<info[i].m; j++) {
685 if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
686 }
687 if (joint[i]->feedback)
688 mfb += info[i].m;
689 }
690
691 // we need a copy of Jacobian for joint feedbacks
692 // because it gets destroyed by SOR solver
693 // instead of saving all Jacobian, we can save just rows
694 // for joints, that requested feedback (which is normaly much less)
695 dRealAllocaArray (Jcopy,mfb*12);
696 if (mfb > 0) {
697 mfb = 0;
698 for (i=0; i<nj; i++)
699 if (joint[i]->feedback) {
700 memcpy(Jcopy+mfb*12, J+ofs[i]*12, info[i].m*12*sizeof(dReal));
701 mfb += info[i].m;
702 }
703 }
704
705
706 // create an array of body numbers for each joint row
707 int *jb_ptr = jb;
708 for (i=0; i<nj; i++) {
709 int b1 = (joint[i]->node[0].body) ? (joint[i]->node[0].body->tag) : -1;
710 int b2 = (joint[i]->node[1].body) ? (joint[i]->node[1].body->tag) : -1;
711 for (j=0; j<info[i].m; j++) {
712 jb_ptr[0] = b1;
713 jb_ptr[1] = b2;
714 jb_ptr += 2;
715 }
716 }
717 dIASSERT (jb_ptr == jb+2*m);
718
719 // compute the right hand side `rhs'
720 IFTIMING (dTimerNow ("compute rhs");)
721 dRealAllocaArray (tmp1,nb*6);
722 // put v/h + invM*fe into tmp1
723 for (i=0; i<nb; i++) {
724 dReal body_invMass = body[i]->invMass;
725 for (j=0; j<3; j++) tmp1[i*6+j] = body[i]->facc[j] * body_invMass + body[i]->lvel[j] * stepsize1;
726 dMULTIPLY0_331 (tmp1 + i*6 + 3,invI + i*12,body[i]->tacc);
727 for (j=0; j<3; j++) tmp1[i*6+3+j] += body[i]->avel[j] * stepsize1;
728 }
729
730 // put J*tmp1 into rhs
731 dRealAllocaArray (rhs,m);
732 multiply_J (m,J,jb,tmp1,rhs);
733
734 // complete rhs
735 for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
736
737 // scale CFM
738 for (i=0; i<m; i++) cfm[i] *= stepsize1;
739
740 // load lambda from the value saved on the previous iteration
741 dRealAllocaArray (lambda,m);
742#ifdef WARM_STARTING
743 dSetZero (lambda,m); //@@@ shouldn't be necessary
744 for (i=0; i<nj; i++) {
745 memcpy (lambda+ofs[i],joint[i]->lambda,info[i].m * sizeof(dReal));
746 }
747#endif
748
749 // solve the LCP problem and get lambda and invM*constraint_force
750 IFTIMING (dTimerNow ("solving LCP problem");)
751 dRealAllocaArray (cforce,nb*6);
752 SOR_LCP (m,nb,J,jb,body,invI,lambda,cforce,rhs,lo,hi,cfm,findex,&world->qs);
753
754#ifdef WARM_STARTING
755 // save lambda for the next iteration
756 //@@@ note that this doesn't work for contact joints yet, as they are
757 // recreated every iteration
758 for (i=0; i<nj; i++) {
759 memcpy (joint[i]->lambda,lambda+ofs[i],info[i].m * sizeof(dReal));
760 }
761#endif
762
763 // note that the SOR method overwrites rhs and J at this point, so
764 // they should not be used again.
765
766 // add stepsize * cforce to the body velocity
767 for (i=0; i<nb; i++) {
768 for (j=0; j<3; j++) body[i]->lvel[j] += stepsize * cforce[i*6+j];
769 for (j=0; j<3; j++) body[i]->avel[j] += stepsize * cforce[i*6+3+j];
770 }
771
772 // if joint feedback is requested, compute the constraint force.
773 // BUT: cforce is inv(M)*J'*lambda, whereas we want just J'*lambda,
774 // so we must compute M*cforce.
775 // @@@ if any joint has a feedback request we compute the entire
776 // adjusted cforce, which is not the most efficient way to do it.
777 /*for (j=0; j<nj; j++) {
778 if (joint[j]->feedback) {
779 // compute adjusted cforce
780 for (i=0; i<nb; i++) {
781 dReal k = body[i]->mass.mass;
782 cforce [i*6+0] *= k;
783 cforce [i*6+1] *= k;
784 cforce [i*6+2] *= k;
785 dVector3 tmp;
786 dMULTIPLY0_331 (tmp, I + 12*i, cforce + i*6 + 3);
787 cforce [i*6+3] = tmp[0];
788 cforce [i*6+4] = tmp[1];
789 cforce [i*6+5] = tmp[2];
790 }
791 // compute feedback for this and all remaining joints
792 for (; j<nj; j++) {
793 dJointFeedback *fb = joint[j]->feedback;
794 if (fb) {
795 int b1 = joint[j]->node[0].body->tag;
796 memcpy (fb->f1,cforce+b1*6,3*sizeof(dReal));
797 memcpy (fb->t1,cforce+b1*6+3,3*sizeof(dReal));
798 if (joint[j]->node[1].body) {
799 int b2 = joint[j]->node[1].body->tag;
800 memcpy (fb->f2,cforce+b2*6,3*sizeof(dReal));
801 memcpy (fb->t2,cforce+b2*6+3,3*sizeof(dReal));
802 }
803 }
804 }
805 }
806 }*/
807
808 if (mfb > 0) {
809 // straightforward computation of joint constraint forces:
810 // multiply related lambdas with respective J' block for joints
811 // where feedback was requested
812 mfb = 0;
813 for (i=0; i<nj; i++) {
814 if (joint[i]->feedback) {
815 dJointFeedback *fb = joint[i]->feedback;
816 dReal data[6];
817 Multiply1_12q1 (data, Jcopy+mfb*12, lambda+ofs[i], info[i].m);
818 fb->f1[0] = data[0];
819 fb->f1[1] = data[1];
820 fb->f1[2] = data[2];
821 fb->t1[0] = data[3];
822 fb->t1[1] = data[4];
823 fb->t1[2] = data[5];
824 if (joint[i]->node[1].body)
825 {
826 Multiply1_12q1 (data, Jcopy+mfb*12+6, lambda+ofs[i], info[i].m);
827 fb->f2[0] = data[0];
828 fb->f2[1] = data[1];
829 fb->f2[2] = data[2];
830 fb->t2[0] = data[3];
831 fb->t2[1] = data[4];
832 fb->t2[2] = data[5];
833 }
834 mfb += info[i].m;
835 }
836 }
837 }
838 }
839
840 // compute the velocity update:
841 // add stepsize * invM * fe to the body velocity
842
843 IFTIMING (dTimerNow ("compute velocity update");)
844 for (i=0; i<nb; i++) {
845 dReal body_invMass = body[i]->invMass;
846 for (j=0; j<3; j++) body[i]->lvel[j] += stepsize * body_invMass * body[i]->facc[j];
847 for (j=0; j<3; j++) body[i]->tacc[j] *= stepsize;
848 dMULTIPLYADD0_331 (body[i]->avel,invI + i*12,body[i]->tacc);
849 }
850
851#if 0
852 // check that the updated velocity obeys the constraint (this check needs unmodified J)
853 dRealAllocaArray (vel,nb*6);
854 for (i=0; i<nb; i++) {
855 for (j=0; j<3; j++) vel[i*6+j] = body[i]->lvel[j];
856 for (j=0; j<3; j++) vel[i*6+3+j] = body[i]->avel[j];
857 }
858 dRealAllocaArray (tmp,m);
859 multiply_J (m,J,jb,vel,tmp);
860 dReal error = 0;
861 for (i=0; i<m; i++) error += dFabs(tmp[i]);
862 printf ("velocity error = %10.6e\n",error);
863#endif
864
865 // update the position and orientation from the new linear/angular velocity
866 // (over the given timestep)
867 IFTIMING (dTimerNow ("update position");)
868 for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
869
870 IFTIMING (dTimerNow ("tidy up");)
871
872 // zero all force accumulators
873 for (i=0; i<nb; i++) {
874 dSetZero (body[i]->facc,3);
875 dSetZero (body[i]->tacc,3);
876 }
877
878 IFTIMING (dTimerEnd();)
879 IFTIMING (if (m > 0) dTimerReport (stdout,1);)
880}
diff --git a/libraries/ode-0.9/ode/src/quickstep.h b/libraries/ode-0.9/ode/src/quickstep.h
deleted file mode 100644
index 43863e7..0000000
--- a/libraries/ode-0.9/ode/src/quickstep.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifndef _ODE_QUICK_STEP_H_
24#define _ODE_QUICK_STEP_H_
25
26#include <ode/common.h>
27
28
29void dxQuickStepper (dxWorld *world, dxBody * const *body, int nb,
30 dxJoint * const *_joint, int nj, dReal stepsize);
31
32
33#endif
diff --git a/libraries/ode-0.9/ode/src/ray.cpp b/libraries/ode-0.9/ode/src/ray.cpp
deleted file mode 100644
index adf61ac..0000000
--- a/libraries/ode-0.9/ode/src/ray.cpp
+++ /dev/null
@@ -1,686 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45//****************************************************************************
46// ray public API
47
48dxRay::dxRay (dSpaceID space, dReal _length) : dxGeom (space,1)
49{
50 type = dRayClass;
51 length = _length;
52}
53
54
55void dxRay::computeAABB()
56{
57 dVector3 e;
58 e[0] = final_posr->pos[0] + final_posr->R[0*4+2]*length;
59 e[1] = final_posr->pos[1] + final_posr->R[1*4+2]*length;
60 e[2] = final_posr->pos[2] + final_posr->R[2*4+2]*length;
61
62 if (final_posr->pos[0] < e[0]){
63 aabb[0] = final_posr->pos[0];
64 aabb[1] = e[0];
65 }
66 else{
67 aabb[0] = e[0];
68 aabb[1] = final_posr->pos[0];
69 }
70
71 if (final_posr->pos[1] < e[1]){
72 aabb[2] = final_posr->pos[1];
73 aabb[3] = e[1];
74 }
75 else{
76 aabb[2] = e[1];
77 aabb[3] = final_posr->pos[1];
78 }
79
80 if (final_posr->pos[2] < e[2]){
81 aabb[4] = final_posr->pos[2];
82 aabb[5] = e[2];
83 }
84 else{
85 aabb[4] = e[2];
86 aabb[5] = final_posr->pos[2];
87 }
88}
89
90
91dGeomID dCreateRay (dSpaceID space, dReal length)
92{
93 return new dxRay (space,length);
94}
95
96
97void dGeomRaySetLength (dGeomID g, dReal length)
98{
99 dUASSERT (g && g->type == dRayClass,"argument not a ray");
100 dxRay *r = (dxRay*) g;
101 r->length = length;
102 dGeomMoved (g);
103}
104
105
106dReal dGeomRayGetLength (dGeomID g)
107{
108 dUASSERT (g && g->type == dRayClass,"argument not a ray");
109 dxRay *r = (dxRay*) g;
110 return r->length;
111}
112
113
114void dGeomRaySet (dGeomID g, dReal px, dReal py, dReal pz,
115 dReal dx, dReal dy, dReal dz)
116{
117 dUASSERT (g && g->type == dRayClass,"argument not a ray");
118 g->recomputePosr();
119 dReal* rot = g->final_posr->R;
120 dReal* pos = g->final_posr->pos;
121 dVector3 n;
122 pos[0] = px;
123 pos[1] = py;
124 pos[2] = pz;
125
126 n[0] = dx;
127 n[1] = dy;
128 n[2] = dz;
129 dNormalize3(n);
130 rot[0*4+2] = n[0];
131 rot[1*4+2] = n[1];
132 rot[2*4+2] = n[2];
133 dGeomMoved (g);
134}
135
136
137void dGeomRayGet (dGeomID g, dVector3 start, dVector3 dir)
138{
139 dUASSERT (g && g->type == dRayClass,"argument not a ray");
140 g->recomputePosr();
141 start[0] = g->final_posr->pos[0];
142 start[1] = g->final_posr->pos[1];
143 start[2] = g->final_posr->pos[2];
144 dir[0] = g->final_posr->R[0*4+2];
145 dir[1] = g->final_posr->R[1*4+2];
146 dir[2] = g->final_posr->R[2*4+2];
147}
148
149
150void dGeomRaySetParams (dxGeom *g, int FirstContact, int BackfaceCull)
151{
152 dUASSERT (g && g->type == dRayClass,"argument not a ray");
153
154 if (FirstContact){
155 g->gflags |= RAY_FIRSTCONTACT;
156 }
157 else g->gflags &= ~RAY_FIRSTCONTACT;
158
159 if (BackfaceCull){
160 g->gflags |= RAY_BACKFACECULL;
161 }
162 else g->gflags &= ~RAY_BACKFACECULL;
163}
164
165
166void dGeomRayGetParams (dxGeom *g, int *FirstContact, int *BackfaceCull)
167{
168 dUASSERT (g && g->type == dRayClass,"argument not a ray");
169
170 (*FirstContact) = ((g->gflags & RAY_FIRSTCONTACT) != 0);
171 (*BackfaceCull) = ((g->gflags & RAY_BACKFACECULL) != 0);
172}
173
174
175void dGeomRaySetClosestHit (dxGeom *g, int closestHit)
176{
177 dUASSERT (g && g->type == dRayClass,"argument not a ray");
178 if (closestHit){
179 g->gflags |= RAY_CLOSEST_HIT;
180 }
181 else g->gflags &= ~RAY_CLOSEST_HIT;
182}
183
184
185int dGeomRayGetClosestHit (dxGeom *g)
186{
187 dUASSERT (g && g->type == dRayClass,"argument not a ray");
188 return ((g->gflags & RAY_CLOSEST_HIT) != 0);
189}
190
191
192
193// if mode==1 then use the sphere exit contact, not the entry contact
194
195static int ray_sphere_helper (dxRay *ray, dVector3 sphere_pos, dReal radius,
196 dContactGeom *contact, int mode)
197{
198 dVector3 q;
199 q[0] = ray->final_posr->pos[0] - sphere_pos[0];
200 q[1] = ray->final_posr->pos[1] - sphere_pos[1];
201 q[2] = ray->final_posr->pos[2] - sphere_pos[2];
202 dReal B = dDOT14(q,ray->final_posr->R+2);
203 dReal C = dDOT(q,q) - radius*radius;
204 // note: if C <= 0 then the start of the ray is inside the sphere
205 dReal k = B*B - C;
206 if (k < 0) return 0;
207 k = dSqrt(k);
208 dReal alpha;
209 if (mode && C >= 0) {
210 alpha = -B + k;
211 if (alpha < 0) return 0;
212 }
213 else {
214 alpha = -B - k;
215 if (alpha < 0) {
216 alpha = -B + k;
217 if (alpha < 0) return 0;
218 }
219 }
220 if (alpha > ray->length) return 0;
221 contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
222 contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
223 contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
224 dReal nsign = (C < 0 || mode) ? REAL(-1.0) : REAL(1.0);
225 contact->normal[0] = nsign*(contact->pos[0] - sphere_pos[0]);
226 contact->normal[1] = nsign*(contact->pos[1] - sphere_pos[1]);
227 contact->normal[2] = nsign*(contact->pos[2] - sphere_pos[2]);
228 dNormalize3 (contact->normal);
229 contact->depth = alpha;
230 return 1;
231}
232
233
234int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags,
235 dContactGeom *contact, int skip)
236{
237 dIASSERT (skip >= (int)sizeof(dContactGeom));
238 dIASSERT (o1->type == dRayClass);
239 dIASSERT (o2->type == dSphereClass);
240 dIASSERT ((flags & NUMC_MASK) >= 1);
241
242 dxRay *ray = (dxRay*) o1;
243 dxSphere *sphere = (dxSphere*) o2;
244 contact->g1 = ray;
245 contact->g2 = sphere;
246 return ray_sphere_helper (ray,sphere->final_posr->pos,sphere->radius,contact,0);
247}
248
249
250int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags,
251 dContactGeom *contact, int skip)
252{
253 dIASSERT (skip >= (int)sizeof(dContactGeom));
254 dIASSERT (o1->type == dRayClass);
255 dIASSERT (o2->type == dBoxClass);
256 dIASSERT ((flags & NUMC_MASK) >= 1);
257
258 dxRay *ray = (dxRay*) o1;
259 dxBox *box = (dxBox*) o2;
260
261 contact->g1 = ray;
262 contact->g2 = box;
263
264 int i;
265
266 // compute the start and delta of the ray relative to the box.
267 // we will do all subsequent computations in this box-relative coordinate
268 // system. we have to do a translation and rotation for each point.
269 dVector3 tmp,s,v;
270 tmp[0] = ray->final_posr->pos[0] - box->final_posr->pos[0];
271 tmp[1] = ray->final_posr->pos[1] - box->final_posr->pos[1];
272 tmp[2] = ray->final_posr->pos[2] - box->final_posr->pos[2];
273 dMULTIPLY1_331 (s,box->final_posr->R,tmp);
274 tmp[0] = ray->final_posr->R[0*4+2];
275 tmp[1] = ray->final_posr->R[1*4+2];
276 tmp[2] = ray->final_posr->R[2*4+2];
277 dMULTIPLY1_331 (v,box->final_posr->R,tmp);
278
279 // mirror the line so that v has all components >= 0
280 dVector3 sign;
281 for (i=0; i<3; i++) {
282 if (v[i] < 0) {
283 s[i] = -s[i];
284 v[i] = -v[i];
285 sign[i] = 1;
286 }
287 else sign[i] = -1;
288 }
289
290 // compute the half-sides of the box
291 dReal h[3];
292 h[0] = REAL(0.5) * box->side[0];
293 h[1] = REAL(0.5) * box->side[1];
294 h[2] = REAL(0.5) * box->side[2];
295
296 // do a few early exit tests
297 if ((s[0] < -h[0] && v[0] <= 0) || s[0] > h[0] ||
298 (s[1] < -h[1] && v[1] <= 0) || s[1] > h[1] ||
299 (s[2] < -h[2] && v[2] <= 0) || s[2] > h[2] ||
300 (v[0] == 0 && v[1] == 0 && v[2] == 0)) {
301 return 0;
302 }
303
304 // compute the t=[lo..hi] range for where s+v*t intersects the box
305 dReal lo = -dInfinity;
306 dReal hi = dInfinity;
307 int nlo = 0, nhi = 0;
308 for (i=0; i<3; i++) {
309 if (v[i] != 0) {
310 dReal k = (-h[i] - s[i])/v[i];
311 if (k > lo) {
312 lo = k;
313 nlo = i;
314 }
315 k = (h[i] - s[i])/v[i];
316 if (k < hi) {
317 hi = k;
318 nhi = i;
319 }
320 }
321 }
322
323 // check if the ray intersects
324 if (lo > hi) return 0;
325 dReal alpha;
326 int n;
327 if (lo >= 0) {
328 alpha = lo;
329 n = nlo;
330 }
331 else {
332 alpha = hi;
333 n = nhi;
334 }
335 if (alpha < 0 || alpha > ray->length) return 0;
336 contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
337 contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
338 contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
339 contact->normal[0] = box->final_posr->R[0*4+n] * sign[n];
340 contact->normal[1] = box->final_posr->R[1*4+n] * sign[n];
341 contact->normal[2] = box->final_posr->R[2*4+n] * sign[n];
342 contact->depth = alpha;
343 return 1;
344}
345
346
347int dCollideRayCapsule (dxGeom *o1, dxGeom *o2,
348 int flags, dContactGeom *contact, int skip)
349{
350 dIASSERT (skip >= (int)sizeof(dContactGeom));
351 dIASSERT (o1->type == dRayClass);
352 dIASSERT (o2->type == dCapsuleClass);
353 dIASSERT ((flags & NUMC_MASK) >= 1);
354
355 dxRay *ray = (dxRay*) o1;
356 dxCapsule *ccyl = (dxCapsule*) o2;
357
358 contact->g1 = ray;
359 contact->g2 = ccyl;
360 dReal lz2 = ccyl->lz * REAL(0.5);
361
362 // compute some useful info
363 dVector3 cs,q,r;
364 dReal C,k;
365 cs[0] = ray->final_posr->pos[0] - ccyl->final_posr->pos[0];
366 cs[1] = ray->final_posr->pos[1] - ccyl->final_posr->pos[1];
367 cs[2] = ray->final_posr->pos[2] - ccyl->final_posr->pos[2];
368 k = dDOT41(ccyl->final_posr->R+2,cs); // position of ray start along ccyl axis
369 q[0] = k*ccyl->final_posr->R[0*4+2] - cs[0];
370 q[1] = k*ccyl->final_posr->R[1*4+2] - cs[1];
371 q[2] = k*ccyl->final_posr->R[2*4+2] - cs[2];
372 C = dDOT(q,q) - ccyl->radius*ccyl->radius;
373 // if C < 0 then ray start position within infinite extension of cylinder
374
375 // see if ray start position is inside the capped cylinder
376 int inside_ccyl = 0;
377 if (C < 0) {
378 if (k < -lz2) k = -lz2;
379 else if (k > lz2) k = lz2;
380 r[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2];
381 r[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2];
382 r[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2];
383 if ((ray->final_posr->pos[0]-r[0])*(ray->final_posr->pos[0]-r[0]) +
384 (ray->final_posr->pos[1]-r[1])*(ray->final_posr->pos[1]-r[1]) +
385 (ray->final_posr->pos[2]-r[2])*(ray->final_posr->pos[2]-r[2]) < ccyl->radius*ccyl->radius) {
386 inside_ccyl = 1;
387 }
388 }
389
390 // compute ray collision with infinite cylinder, except for the case where
391 // the ray is outside the capped cylinder but within the infinite cylinder
392 // (it that case the ray can only hit endcaps)
393 if (!inside_ccyl && C < 0) {
394 // set k to cap position to check
395 if (k < 0) k = -lz2; else k = lz2;
396 }
397 else {
398 dReal uv = dDOT44(ccyl->final_posr->R+2,ray->final_posr->R+2);
399 r[0] = uv*ccyl->final_posr->R[0*4+2] - ray->final_posr->R[0*4+2];
400 r[1] = uv*ccyl->final_posr->R[1*4+2] - ray->final_posr->R[1*4+2];
401 r[2] = uv*ccyl->final_posr->R[2*4+2] - ray->final_posr->R[2*4+2];
402 dReal A = dDOT(r,r);
403 dReal B = 2*dDOT(q,r);
404 k = B*B-4*A*C;
405 if (k < 0) {
406 // the ray does not intersect the infinite cylinder, but if the ray is
407 // inside and parallel to the cylinder axis it may intersect the end
408 // caps. set k to cap position to check.
409 if (!inside_ccyl) return 0;
410 if (uv < 0) k = -lz2; else k = lz2;
411 }
412 else {
413 k = dSqrt(k);
414 A = dRecip (2*A);
415 dReal alpha = (-B-k)*A;
416 if (alpha < 0) {
417 alpha = (-B+k)*A;
418 if (alpha < 0) return 0;
419 }
420 if (alpha > ray->length) return 0;
421
422 // the ray intersects the infinite cylinder. check to see if the
423 // intersection point is between the caps
424 contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
425 contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
426 contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
427 q[0] = contact->pos[0] - ccyl->final_posr->pos[0];
428 q[1] = contact->pos[1] - ccyl->final_posr->pos[1];
429 q[2] = contact->pos[2] - ccyl->final_posr->pos[2];
430 k = dDOT14(q,ccyl->final_posr->R+2);
431 dReal nsign = inside_ccyl ? REAL(-1.0) : REAL(1.0);
432 if (k >= -lz2 && k <= lz2) {
433 contact->normal[0] = nsign * (contact->pos[0] -
434 (ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2]));
435 contact->normal[1] = nsign * (contact->pos[1] -
436 (ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2]));
437 contact->normal[2] = nsign * (contact->pos[2] -
438 (ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2]));
439 dNormalize3 (contact->normal);
440 contact->depth = alpha;
441 return 1;
442 }
443
444 // the infinite cylinder intersection point is not between the caps.
445 // set k to cap position to check.
446 if (k < 0) k = -lz2; else k = lz2;
447 }
448 }
449
450 // check for ray intersection with the caps. k must indicate the cap
451 // position to check
452 q[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2];
453 q[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2];
454 q[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2];
455 return ray_sphere_helper (ray,q,ccyl->radius,contact, inside_ccyl);
456}
457
458
459int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags,
460 dContactGeom *contact, int skip)
461{
462 dIASSERT (skip >= (int)sizeof(dContactGeom));
463 dIASSERT (o1->type == dRayClass);
464 dIASSERT (o2->type == dPlaneClass);
465 dIASSERT ((flags & NUMC_MASK) >= 1);
466
467 dxRay *ray = (dxRay*) o1;
468 dxPlane *plane = (dxPlane*) o2;
469
470 dReal alpha = plane->p[3] - dDOT (plane->p,ray->final_posr->pos);
471 // note: if alpha > 0 the starting point is below the plane
472 dReal nsign = (alpha > 0) ? REAL(-1.0) : REAL(1.0);
473 dReal k = dDOT14(plane->p,ray->final_posr->R+2);
474 if (k==0) return 0; // ray parallel to plane
475 alpha /= k;
476 if (alpha < 0 || alpha > ray->length) return 0;
477 contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
478 contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
479 contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
480 contact->normal[0] = nsign*plane->p[0];
481 contact->normal[1] = nsign*plane->p[1];
482 contact->normal[2] = nsign*plane->p[2];
483 contact->depth = alpha;
484 contact->g1 = ray;
485 contact->g2 = plane;
486 return 1;
487}
488
489// Ray - Cylinder collider by David Walters (June 2006)
490int dCollideRayCylinder( dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip )
491{
492 dIASSERT( skip >= (int)sizeof( dContactGeom ) );
493 dIASSERT( o1->type == dRayClass );
494 dIASSERT( o2->type == dCylinderClass );
495 dIASSERT( (flags & NUMC_MASK) >= 1 );
496
497 dxRay* ray = (dxRay*)( o1 );
498 dxCylinder* cyl = (dxCylinder*)( o2 );
499
500 // Fill in contact information.
501 contact->g1 = ray;
502 contact->g2 = cyl;
503
504 const dReal half_length = cyl->lz * REAL( 0.5 );
505
506 //
507 // Compute some useful info
508 //
509
510 dVector3 q, r;
511 dReal d, C, k;
512
513 // Vector 'r', line segment from C to R (ray start) ( r = R - C )
514 r[ 0 ] = ray->final_posr->pos[0] - cyl->final_posr->pos[0];
515 r[ 1 ] = ray->final_posr->pos[1] - cyl->final_posr->pos[1];
516 r[ 2 ] = ray->final_posr->pos[2] - cyl->final_posr->pos[2];
517
518 // Distance that ray start is along cyl axis ( Z-axis direction )
519 d = dDOT41( cyl->final_posr->R + 2, r );
520
521 //
522 // Compute vector 'q' representing the shortest line from R to the cylinder z-axis (Cz).
523 //
524 // Point on axis ( in world space ): cp = ( d * Cz ) + C
525 //
526 // Line 'q' from R to cp: q = cp - R
527 // q = ( d * Cz ) + C - R
528 // q = ( d * Cz ) - ( R - C )
529
530 q[ 0 ] = ( d * cyl->final_posr->R[0*4+2] ) - r[ 0 ];
531 q[ 1 ] = ( d * cyl->final_posr->R[1*4+2] ) - r[ 1 ];
532 q[ 2 ] = ( d * cyl->final_posr->R[2*4+2] ) - r[ 2 ];
533
534
535 // Compute square length of 'q'. Subtract from radius squared to
536 // get square distance 'C' between the line q and the radius.
537
538 // if C < 0 then ray start position is within infinite extension of cylinder
539
540 C = dDOT( q, q ) - ( cyl->radius * cyl->radius );
541
542 // Compute the projection of ray direction normal onto cylinder direction normal.
543 dReal uv = dDOT44( cyl->final_posr->R+2, ray->final_posr->R+2 );
544
545
546
547 //
548 // Find ray collision with infinite cylinder
549 //
550
551 // Compute vector from end of ray direction normal to projection on cylinder direction normal.
552 r[ 0 ] = ( uv * cyl->final_posr->R[0*4+2] ) - ray->final_posr->R[0*4+2];
553 r[ 1 ] = ( uv * cyl->final_posr->R[1*4+2] ) - ray->final_posr->R[1*4+2];
554 r[ 2 ] = ( uv * cyl->final_posr->R[2*4+2] ) - ray->final_posr->R[2*4+2];
555
556
557 // Quadratic Formula Magic
558 // Compute discriminant 'k':
559
560 // k < 0 : No intersection
561 // k = 0 : Tangent
562 // k > 0 : Intersection
563
564 dReal A = dDOT( r, r );
565 dReal B = 2 * dDOT( q, r );
566
567 k = B*B - 4*A*C;
568
569
570
571
572 //
573 // Collision with Flat Caps ?
574 //
575
576 // No collision with cylinder edge. ( Use epsilon here or we miss some obvious cases )
577 if ( k < dEpsilon && C <= 0 )
578 {
579 // The ray does not intersect the edge of the infinite cylinder,
580 // but the ray start is inside and so must run parallel to the axis.
581 // It may yet intersect an end cap. The following cases are valid:
582
583 // -ve-cap , -half centre +half , +ve-cap
584 // <<================|-------------------|------------->>>---|================>>
585 // | |
586 // | d-------------------> 1.
587 // 2. d------------------> |
588 // 3. <------------------d |
589 // | <-------------------d 4.
590 // | |
591 // <<================|-------------------|------------->>>---|===============>>
592
593 // Negative if the ray and cylinder axes point in opposite directions.
594 const dReal uvsign = ( uv < 0 ) ? REAL( -1.0 ) : REAL( 1.0 );
595
596 // Negative if the ray start is inside the cylinder
597 const dReal internal = ( d >= -half_length && d <= +half_length ) ? REAL( -1.0 ) : REAL( 1.0 );
598
599 // Ray and Cylinder axes run in the same direction ( cases 1, 2 )
600 // Ray and Cylinder axes run in opposite directions ( cases 3, 4 )
601 if ( ( ( uv > 0 ) && ( d + ( uvsign * ray->length ) < half_length * internal ) ) ||
602 ( ( uv < 0 ) && ( d + ( uvsign * ray->length ) > half_length * internal ) ) )
603 {
604 return 0; // No intersection with caps or curved surface.
605 }
606
607 // Compute depth (distance from ray to cylinder)
608 contact->depth = ( ( -uvsign * d ) - ( internal * half_length ) );
609
610 // Compute contact point.
611 contact->pos[0] = ray->final_posr->pos[0] + ( contact->depth * ray->final_posr->R[0*4+2] );
612 contact->pos[1] = ray->final_posr->pos[1] + ( contact->depth * ray->final_posr->R[1*4+2] );
613 contact->pos[2] = ray->final_posr->pos[2] + ( contact->depth * ray->final_posr->R[2*4+2] );
614
615 // Compute reflected contact normal.
616 contact->normal[0] = uvsign * ( cyl->final_posr->R[0*4+2] );
617 contact->normal[1] = uvsign * ( cyl->final_posr->R[1*4+2] );
618 contact->normal[2] = uvsign * ( cyl->final_posr->R[2*4+2] );
619
620 // Contact!
621 return 1;
622 }
623
624
625
626 //
627 // Collision with Curved Edge ?
628 //
629
630 if ( k > 0 )
631 {
632 // Finish off quadratic formula to get intersection co-efficient
633 k = dSqrt( k );
634 A = dRecip( 2 * A );
635
636 // Compute distance along line to contact point.
637 dReal alpha = ( -B - k ) * A;
638 if ( alpha < 0 )
639 {
640 // Flip in the other direction.
641 alpha = ( -B + k ) * A;
642 }
643
644 // Intersection point is within ray length?
645 if ( alpha >= 0 && alpha <= ray->length )
646 {
647 // The ray intersects the infinite cylinder!
648
649 // Compute contact point.
650 contact->pos[0] = ray->final_posr->pos[0] + ( alpha * ray->final_posr->R[0*4+2] );
651 contact->pos[1] = ray->final_posr->pos[1] + ( alpha * ray->final_posr->R[1*4+2] );
652 contact->pos[2] = ray->final_posr->pos[2] + ( alpha * ray->final_posr->R[2*4+2] );
653
654 // q is the vector from the cylinder centre to the contact point.
655 q[0] = contact->pos[0] - cyl->final_posr->pos[0];
656 q[1] = contact->pos[1] - cyl->final_posr->pos[1];
657 q[2] = contact->pos[2] - cyl->final_posr->pos[2];
658
659 // Compute the distance along the cylinder axis of this contact point.
660 d = dDOT14( q, cyl->final_posr->R+2 );
661
662 // Check to see if the intersection point is between the flat end caps
663 if ( d >= -half_length && d <= +half_length )
664 {
665 // Flip the normal if the start point is inside the cylinder.
666 const dReal nsign = ( C < 0 ) ? REAL( -1.0 ) : REAL( 1.0 );
667
668 // Compute contact normal.
669 contact->normal[0] = nsign * (contact->pos[0] - (cyl->final_posr->pos[0] + d*cyl->final_posr->R[0*4+2]));
670 contact->normal[1] = nsign * (contact->pos[1] - (cyl->final_posr->pos[1] + d*cyl->final_posr->R[1*4+2]));
671 contact->normal[2] = nsign * (contact->pos[2] - (cyl->final_posr->pos[2] + d*cyl->final_posr->R[2*4+2]));
672 dNormalize3( contact->normal );
673
674 // Store depth.
675 contact->depth = alpha;
676
677 // Contact!
678 return 1;
679 }
680 }
681 }
682
683 // No contact with anything.
684 return 0;
685}
686
diff --git a/libraries/ode-0.9/ode/src/rotation.cpp b/libraries/ode-0.9/ode/src/rotation.cpp
deleted file mode 100644
index adb933b..0000000
--- a/libraries/ode-0.9/ode/src/rotation.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25quaternions have the format: (s,vx,vy,vz) where (vx,vy,vz) is the
26"rotation axis" and s is the "rotation angle".
27
28*/
29
30#include <ode/rotation.h>
31#include <ode/odemath.h>
32
33
34#define _R(i,j) R[(i)*4+(j)]
35
36#define SET_3x3_IDENTITY \
37 _R(0,0) = REAL(1.0); \
38 _R(0,1) = REAL(0.0); \
39 _R(0,2) = REAL(0.0); \
40 _R(0,3) = REAL(0.0); \
41 _R(1,0) = REAL(0.0); \
42 _R(1,1) = REAL(1.0); \
43 _R(1,2) = REAL(0.0); \
44 _R(1,3) = REAL(0.0); \
45 _R(2,0) = REAL(0.0); \
46 _R(2,1) = REAL(0.0); \
47 _R(2,2) = REAL(1.0); \
48 _R(2,3) = REAL(0.0);
49
50
51void dRSetIdentity (dMatrix3 R)
52{
53 dAASSERT (R);
54 SET_3x3_IDENTITY;
55}
56
57
58void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az,
59 dReal angle)
60{
61 dAASSERT (R);
62 dQuaternion q;
63 dQFromAxisAndAngle (q,ax,ay,az,angle);
64 dQtoR (q,R);
65}
66
67
68void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi)
69{
70 dReal sphi,cphi,stheta,ctheta,spsi,cpsi;
71 dAASSERT (R);
72 sphi = dSin(phi);
73 cphi = dCos(phi);
74 stheta = dSin(theta);
75 ctheta = dCos(theta);
76 spsi = dSin(psi);
77 cpsi = dCos(psi);
78 _R(0,0) = cpsi*ctheta;
79 _R(0,1) = spsi*ctheta;
80 _R(0,2) =-stheta;
81 _R(0,3) = REAL(0.0);
82 _R(1,0) = cpsi*stheta*sphi - spsi*cphi;
83 _R(1,1) = spsi*stheta*sphi + cpsi*cphi;
84 _R(1,2) = ctheta*sphi;
85 _R(1,3) = REAL(0.0);
86 _R(2,0) = cpsi*stheta*cphi + spsi*sphi;
87 _R(2,1) = spsi*stheta*cphi - cpsi*sphi;
88 _R(2,2) = ctheta*cphi;
89 _R(2,3) = REAL(0.0);
90}
91
92
93void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az,
94 dReal bx, dReal by, dReal bz)
95{
96 dReal l,k;
97 dAASSERT (R);
98 l = dSqrt (ax*ax + ay*ay + az*az);
99 if (l <= REAL(0.0)) {
100 dDEBUGMSG ("zero length vector");
101 return;
102 }
103 l = dRecip(l);
104 ax *= l;
105 ay *= l;
106 az *= l;
107 k = ax*bx + ay*by + az*bz;
108 bx -= k*ax;
109 by -= k*ay;
110 bz -= k*az;
111 l = dSqrt (bx*bx + by*by + bz*bz);
112 if (l <= REAL(0.0)) {
113 dDEBUGMSG ("zero length vector");
114 return;
115 }
116 l = dRecip(l);
117 bx *= l;
118 by *= l;
119 bz *= l;
120 _R(0,0) = ax;
121 _R(1,0) = ay;
122 _R(2,0) = az;
123 _R(0,1) = bx;
124 _R(1,1) = by;
125 _R(2,1) = bz;
126 _R(0,2) = - by*az + ay*bz;
127 _R(1,2) = - bz*ax + az*bx;
128 _R(2,2) = - bx*ay + ax*by;
129 _R(0,3) = REAL(0.0);
130 _R(1,3) = REAL(0.0);
131 _R(2,3) = REAL(0.0);
132}
133
134
135void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az)
136{
137 dVector3 n,p,q;
138 n[0] = ax;
139 n[1] = ay;
140 n[2] = az;
141 dNormalize3 (n);
142 dPlaneSpace (n,p,q);
143 _R(0,0) = p[0];
144 _R(1,0) = p[1];
145 _R(2,0) = p[2];
146 _R(0,1) = q[0];
147 _R(1,1) = q[1];
148 _R(2,1) = q[2];
149 _R(0,2) = n[0];
150 _R(1,2) = n[1];
151 _R(2,2) = n[2];
152 _R(0,3) = REAL(0.0);
153 _R(1,3) = REAL(0.0);
154 _R(2,3) = REAL(0.0);
155}
156
157
158void dQSetIdentity (dQuaternion q)
159{
160 dAASSERT (q);
161 q[0] = 1;
162 q[1] = 0;
163 q[2] = 0;
164 q[3] = 0;
165}
166
167
168void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az,
169 dReal angle)
170{
171 dAASSERT (q);
172 dReal l = ax*ax + ay*ay + az*az;
173 if (l > REAL(0.0)) {
174 angle *= REAL(0.5);
175 q[0] = dCos (angle);
176 l = dSin(angle) * dRecipSqrt(l);
177 q[1] = ax*l;
178 q[2] = ay*l;
179 q[3] = az*l;
180 }
181 else {
182 q[0] = 1;
183 q[1] = 0;
184 q[2] = 0;
185 q[3] = 0;
186 }
187}
188
189
190void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
191{
192 dAASSERT (qa && qb && qc);
193 qa[0] = qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3];
194 qa[1] = qb[0]*qc[1] + qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2];
195 qa[2] = qb[0]*qc[2] + qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3];
196 qa[3] = qb[0]*qc[3] + qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1];
197}
198
199
200void dQMultiply1 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
201{
202 dAASSERT (qa && qb && qc);
203 qa[0] = qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3];
204 qa[1] = qb[0]*qc[1] - qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2];
205 qa[2] = qb[0]*qc[2] - qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3];
206 qa[3] = qb[0]*qc[3] - qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1];
207}
208
209
210void dQMultiply2 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
211{
212 dAASSERT (qa && qb && qc);
213 qa[0] = qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3];
214 qa[1] = -qb[0]*qc[1] + qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2];
215 qa[2] = -qb[0]*qc[2] + qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3];
216 qa[3] = -qb[0]*qc[3] + qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1];
217}
218
219
220void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
221{
222 dAASSERT (qa && qb && qc);
223 qa[0] = qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3];
224 qa[1] = -qb[0]*qc[1] - qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2];
225 qa[2] = -qb[0]*qc[2] - qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3];
226 qa[3] = -qb[0]*qc[3] - qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1];
227}
228
229
230// dRfromQ(), dQfromR() and dDQfromW() are derived from equations in "An Introduction
231// to Physically Based Modeling: Rigid Body Simulation - 1: Unconstrained
232// Rigid Body Dynamics" by David Baraff, Robotics Institute, Carnegie Mellon
233// University, 1997.
234
235void dRfromQ (dMatrix3 R, const dQuaternion q)
236{
237 dAASSERT (q && R);
238 // q = (s,vx,vy,vz)
239 dReal qq1 = 2*q[1]*q[1];
240 dReal qq2 = 2*q[2]*q[2];
241 dReal qq3 = 2*q[3]*q[3];
242 _R(0,0) = 1 - qq2 - qq3;
243 _R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]);
244 _R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]);
245 _R(0,3) = REAL(0.0);
246 _R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]);
247 _R(1,1) = 1 - qq1 - qq3;
248 _R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]);
249 _R(1,3) = REAL(0.0);
250 _R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]);
251 _R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]);
252 _R(2,2) = 1 - qq1 - qq2;
253 _R(2,3) = REAL(0.0);
254}
255
256
257void dQfromR (dQuaternion q, const dMatrix3 R)
258{
259 dAASSERT (q && R);
260 dReal tr,s;
261 tr = _R(0,0) + _R(1,1) + _R(2,2);
262 if (tr >= 0) {
263 s = dSqrt (tr + 1);
264 q[0] = REAL(0.5) * s;
265 s = REAL(0.5) * dRecip(s);
266 q[1] = (_R(2,1) - _R(1,2)) * s;
267 q[2] = (_R(0,2) - _R(2,0)) * s;
268 q[3] = (_R(1,0) - _R(0,1)) * s;
269 }
270 else {
271 // find the largest diagonal element and jump to the appropriate case
272 if (_R(1,1) > _R(0,0)) {
273 if (_R(2,2) > _R(1,1)) goto case_2;
274 goto case_1;
275 }
276 if (_R(2,2) > _R(0,0)) goto case_2;
277 goto case_0;
278
279 case_0:
280 s = dSqrt((_R(0,0) - (_R(1,1) + _R(2,2))) + 1);
281 q[1] = REAL(0.5) * s;
282 s = REAL(0.5) * dRecip(s);
283 q[2] = (_R(0,1) + _R(1,0)) * s;
284 q[3] = (_R(2,0) + _R(0,2)) * s;
285 q[0] = (_R(2,1) - _R(1,2)) * s;
286 return;
287
288 case_1:
289 s = dSqrt((_R(1,1) - (_R(2,2) + _R(0,0))) + 1);
290 q[2] = REAL(0.5) * s;
291 s = REAL(0.5) * dRecip(s);
292 q[3] = (_R(1,2) + _R(2,1)) * s;
293 q[1] = (_R(0,1) + _R(1,0)) * s;
294 q[0] = (_R(0,2) - _R(2,0)) * s;
295 return;
296
297 case_2:
298 s = dSqrt((_R(2,2) - (_R(0,0) + _R(1,1))) + 1);
299 q[3] = REAL(0.5) * s;
300 s = REAL(0.5) * dRecip(s);
301 q[1] = (_R(2,0) + _R(0,2)) * s;
302 q[2] = (_R(1,2) + _R(2,1)) * s;
303 q[0] = (_R(1,0) - _R(0,1)) * s;
304 return;
305 }
306}
307
308
309void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q)
310{
311 dAASSERT (w && q && dq);
312 dq[0] = REAL(0.5)*(- w[0]*q[1] - w[1]*q[2] - w[2]*q[3]);
313 dq[1] = REAL(0.5)*( w[0]*q[0] + w[1]*q[3] - w[2]*q[2]);
314 dq[2] = REAL(0.5)*(- w[0]*q[3] + w[1]*q[0] + w[2]*q[1]);
315 dq[3] = REAL(0.5)*( w[0]*q[2] - w[1]*q[1] + w[2]*q[0]);
316}
diff --git a/libraries/ode-0.9/ode/src/scrapbook.cpp b/libraries/ode-0.9/ode/src/scrapbook.cpp
deleted file mode 100644
index 2621814..0000000
--- a/libraries/ode-0.9/ode/src/scrapbook.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
1
2/*
3
4this is code that was once useful but has now been obseleted.
5
6this file should not be compiled as part of ODE!
7
8*/
9
10//***************************************************************************
11// intersect a line segment with a plane
12
13extern "C" int dClipLineToBox (const dVector3 p1, const dVector3 p2,
14 const dVector3 p, const dMatrix3 R,
15 const dVector3 side)
16{
17 // compute the start and end of the line (p1 and p2) relative to the box.
18 // we will do all subsequent computations in this box-relative coordinate
19 // system. we have to do a translation and rotation for each point.
20 dVector3 tmp,s,e;
21 tmp[0] = p1[0] - p[0];
22 tmp[1] = p1[1] - p[1];
23 tmp[2] = p1[2] - p[2];
24 dMULTIPLY1_331 (s,R,tmp);
25 tmp[0] = p2[0] - p[0];
26 tmp[1] = p2[1] - p[1];
27 tmp[2] = p2[2] - p[2];
28 dMULTIPLY1_331 (e,R,tmp);
29
30 // compute the vector 'v' from the start point to the end point
31 dVector3 v;
32 v[0] = e[0] - s[0];
33 v[1] = e[1] - s[1];
34 v[2] = e[2] - s[2];
35
36 // a point on the line is defined by the parameter 't'. t=0 corresponds
37 // to the start of the line, t=1 corresponds to the end of the line.
38 // we will clip the line to the box by finding the range of t where a
39 // point on the line is inside the box. the currently known bounds for
40 // t and tlo..thi.
41 dReal tlo=0,thi=1;
42
43 // clip in the X/Y/Z direction
44 for (int i=0; i<3; i++) {
45 // first adjust s,e for the current t range. this is redundant for the
46 // first iteration, but never mind.
47 e[i] = s[i] + thi*v[i];
48 s[i] = s[i] + tlo*v[i];
49 // compute where t intersects the positive and negative sides.
50 dReal tp = ( side[i] - s[i])/v[i]; // @@@ handle case where denom=0
51 dReal tm = (-side[i] - s[i])/v[i];
52 // handle 9 intersection cases
53 if (s[i] <= -side[i]) {
54 tlo = tm;
55 if (e[i] <= -side[i]) return 0;
56 else if (e[i] >= side[i]) thi = tp;
57 }
58 else if (s[i] <= side[i]) {
59 if (e[i] <= -side[i]) thi = tm;
60 else if (e[i] >= side[i]) thi = tp;
61 }
62 else {
63 tlo = tp;
64 if (e[i] <= -side[i]) thi = tm;
65 else if (e[i] >= side[i]) return 0;
66 }
67 }
68
69 //... @@@ AT HERE @@@
70
71 return 1;
72}
73
74
75//***************************************************************************
76// a nice try at C-B collision. unfortunately it doesn't work. the logic
77// for testing for line-box intersection is correct, but unfortunately the
78// closest-point distance estimates are often too large. as a result contact
79// points are placed incorrectly.
80
81
82int dCollideCB (const dxGeom *o1, const dxGeom *o2, int flags,
83 dContactGeom *contact, int skip)
84{
85 int i;
86
87 dIASSERT (skip >= (int)sizeof(dContactGeom));
88 dIASSERT (o1->_class->num == dCCylinderClass);
89 dIASSERT (o2->_class->num == dBoxClass);
90 contact->g1 = const_cast<dxGeom*> (o1);
91 contact->g2 = const_cast<dxGeom*> (o2);
92 dxCCylinder *cyl = (dxCCylinder*) CLASSDATA(o1);
93 dxBox *box = (dxBox*) CLASSDATA(o2);
94
95 // get p1,p2 = cylinder axis endpoints, get radius
96 dVector3 p1,p2;
97 dReal clen = cyl->lz * REAL(0.5);
98 p1[0] = o1->pos[0] + clen * o1->R[2];
99 p1[1] = o1->pos[1] + clen * o1->R[6];
100 p1[2] = o1->pos[2] + clen * o1->R[10];
101 p2[0] = o1->pos[0] - clen * o1->R[2];
102 p2[1] = o1->pos[1] - clen * o1->R[6];
103 p2[2] = o1->pos[2] - clen * o1->R[10];
104 dReal radius = cyl->radius;
105
106 // copy out box center, rotation matrix, and side array
107 dReal *c = o2->pos;
108 dReal *R = o2->R;
109 dReal *side = box->side;
110
111 // compute the start and end of the line (p1 and p2) relative to the box.
112 // we will do all subsequent computations in this box-relative coordinate
113 // system. we have to do a translation and rotation for each point.
114 dVector3 tmp3,s,e;
115 tmp3[0] = p1[0] - c[0];
116 tmp3[1] = p1[1] - c[1];
117 tmp3[2] = p1[2] - c[2];
118 dMULTIPLY1_331 (s,R,tmp3);
119 tmp3[0] = p2[0] - c[0];
120 tmp3[1] = p2[1] - c[1];
121 tmp3[2] = p2[2] - c[2];
122 dMULTIPLY1_331 (e,R,tmp3);
123
124 // compute the vector 'v' from the start point to the end point
125 dVector3 v;
126 v[0] = e[0] - s[0];
127 v[1] = e[1] - s[1];
128 v[2] = e[2] - s[2];
129
130 // compute the half-sides of the box
131 dReal S0 = side[0] * REAL(0.5);
132 dReal S1 = side[1] * REAL(0.5);
133 dReal S2 = side[2] * REAL(0.5);
134
135 // compute the size of the bounding box around the line segment
136 dReal B0 = dFabs (v[0]);
137 dReal B1 = dFabs (v[1]);
138 dReal B2 = dFabs (v[2]);
139
140 // for all 6 separation axes, measure the penetration depth. if any depth is
141 // less than 0 then the objects don't penetrate at all so we can just
142 // return 0. find the axis with the smallest depth, and record its normal.
143
144 // note: normalR is set to point to a column of R if that is the smallest
145 // depth normal so far. otherwise normalR is 0 and normalC is set to a
146 // vector relative to the box. invert_normal is 1 if the sign of the normal
147 // should be flipped.
148
149 dReal depth,trial_depth,tmp,length;
150 const dReal *normalR=0;
151 dVector3 normalC;
152 int invert_normal = 0;
153 int code = 0; // 0=no contact, 1-3=face contact, 4-6=edge contact
154
155 depth = dInfinity;
156
157 // look at face-normal axes
158
159#undef TEST
160#define TEST(center,depth_expr,norm,contact_code) \
161 tmp = (center); \
162 trial_depth = radius + REAL(0.5) * ((depth_expr) - dFabs(tmp)); \
163 if (trial_depth < 0) return 0; \
164 if (trial_depth < depth) { \
165 depth = trial_depth; \
166 normalR = (norm); \
167 invert_normal = (tmp < 0); \
168 code = contact_code; \
169 }
170
171 TEST (s[0]+e[0], side[0] + B0, R+0, 1);
172 TEST (s[1]+e[1], side[1] + B1, R+1, 2);
173 TEST (s[2]+e[2], side[2] + B2, R+2, 3);
174
175 // look at v x box-edge axes
176
177#undef TEST
178#define TEST(box_radius,line_offset,nx,ny,nz,contact_code) \
179 tmp = (line_offset); \
180 trial_depth = (box_radius) - dFabs(tmp); \
181 length = dSqrt ((nx)*(nx) + (ny)*(ny) + (nz)*(nz)); \
182 if (length > 0) { \
183 length = dRecip(length); \
184 trial_depth = trial_depth * length + radius; \
185 if (trial_depth < 0) return 0; \
186 if (trial_depth < depth) { \
187 depth = trial_depth; \
188 normalR = 0; \
189 normalC[0] = (nx)*length; \
190 normalC[1] = (ny)*length; \
191 normalC[2] = (nz)*length; \
192 invert_normal = (tmp < 0); \
193 code = contact_code; \
194 } \
195 }
196
197 TEST (B2*S1+B1*S2,v[1]*s[2]-v[2]*s[1], 0,-v[2],v[1], 4);
198 TEST (B2*S0+B0*S2,v[2]*s[0]-v[0]*s[2], v[2],0,-v[0], 5);
199 TEST (B1*S0+B0*S1,v[0]*s[1]-v[1]*s[0], -v[1],v[0],0, 6);
200
201#undef TEST
202
203 // if we get to this point, the box and ccylinder interpenetrate.
204 // compute the normal in global coordinates.
205 dReal *normal = contact[0].normal;
206 if (normalR) {
207 normal[0] = normalR[0];
208 normal[1] = normalR[4];
209 normal[2] = normalR[8];
210 }
211 else {
212 dMULTIPLY0_331 (normal,R,normalC);
213 }
214 if (invert_normal) {
215 normal[0] = -normal[0];
216 normal[1] = -normal[1];
217 normal[2] = -normal[2];
218 }
219
220 // set the depth
221 contact[0].depth = depth;
222
223 if (code == 0) {
224 return 0; // should never get here
225 }
226 else if (code >= 4) {
227 // handle edge contacts
228 // find an endpoint q1 on the intersecting edge of the box
229 dVector3 q1;
230 dReal sign[3];
231 for (i=0; i<3; i++) q1[i] = c[i];
232 sign[0] = (dDOT14(normal,R+0) > 0) ? REAL(1.0) : REAL(-1.0);
233 for (i=0; i<3; i++) q1[i] += sign[0] * S0 * R[i*4];
234 sign[1] = (dDOT14(normal,R+1) > 0) ? REAL(1.0) : REAL(-1.0);
235 for (i=0; i<3; i++) q1[i] += sign[1] * S1 * R[i*4+1];
236 sign[2] = (dDOT14(normal,R+2) > 0) ? REAL(1.0) : REAL(-1.0);
237 for (i=0; i<3; i++) q1[i] += sign[2] * S2 * R[i*4+2];
238
239 // find the other endpoint q2 of the intersecting edge
240 dVector3 q2;
241 for (i=0; i<3; i++)
242 q2[i] = q1[i] - R[code-4 + i*4] * (sign[code-4] * side[code-4]);
243
244 // determine the closest point between the box edge and the line segment
245 dVector3 cp1,cp2;
246 dClosestLineSegmentPoints (q1,q2, p1,p2, cp1,cp2);
247 for (i=0; i<3; i++) contact[0].pos[i] = cp1[i] - REAL(0.5)*normal[i]*depth;
248 return 1;
249 }
250 else {
251 // handle face contacts.
252 // @@@ temporary: make deepest vertex on the line the contact point.
253 // @@@ this kind of works, but we sometimes need two contact points for
254 // @@@ stability.
255
256 // compute 'v' in global coordinates
257 dVector3 gv;
258 for (i=0; i<3; i++) gv[i] = p2[i] - p1[i];
259
260 if (dDOT (normal,gv) > 0) {
261 for (i=0; i<3; i++)
262 contact[0].pos[i] = p1[i] + (depth*REAL(0.5)-radius)*normal[i];
263 }
264 else {
265 for (i=0; i<3; i++)
266 contact[0].pos[i] = p2[i] + (depth*REAL(0.5)-radius)*normal[i];
267 }
268 return 1;
269 }
270}
271
272//***************************************************************************
273// this function works, it's just not being used for anything at the moment:
274
275// given a box (R,side), `R' is the rotation matrix for the box, and `side'
276// is a vector of x/y/z side lengths, return the size of the interval of the
277// box projected along the given axis. if the axis has unit length then the
278// return value will be the actual diameter, otherwise the result will be
279// scaled by the axis length.
280
281static inline dReal boxDiameter (const dMatrix3 R, const dVector3 side,
282 const dVector3 axis)
283{
284 dVector3 q;
285 dMULTIPLY1_331 (q,R,axis); // transform axis to body-relative
286 return dFabs(q[0])*side[0] + dFabs(q[1])*side[1] + dFabs(q[2])*side[2];
287}
288
289//***************************************************************************
290// the old capped cylinder to capped cylinder collision code. this fails to
291// detect cap-to-cap contact points when the cylinder axis are aligned, but
292// other that that it is pretty robust.
293
294// this returns at most one contact point when the two cylinder's axes are not
295// aligned, and at most two (for stability) when they are aligned.
296// the algorithm minimizes the distance between two "sample spheres" that are
297// positioned along the cylinder axes according to:
298// sphere1 = pos1 + alpha1 * axis1
299// sphere2 = pos2 + alpha2 * axis2
300// alpha1 and alpha2 are limited to +/- half the length of the cylinders.
301// the algorithm works by finding a solution that has both alphas free, or
302// a solution that has one or both alphas fixed to the ends of the cylinder.
303
304int dCollideCCylinderCCylinder (dxGeom *o1, dxGeom *o2,
305 int flags, dContactGeom *contact, int skip)
306{
307 int i;
308 const dReal tolerance = REAL(1e-5);
309
310 dIASSERT (skip >= (int)sizeof(dContactGeom));
311 dIASSERT (o1->type == dCCylinderClass);
312 dIASSERT (o2->type == dCCylinderClass);
313 dxCCylinder *cyl1 = (dxCCylinder*) o1;
314 dxCCylinder *cyl2 = (dxCCylinder*) o2;
315
316 contact->g1 = o1;
317 contact->g2 = o2;
318
319 // copy out some variables, for convenience
320 dReal lz1 = cyl1->lz * REAL(0.5);
321 dReal lz2 = cyl2->lz * REAL(0.5);
322 dReal *pos1 = o1->pos;
323 dReal *pos2 = o2->pos;
324 dReal axis1[3],axis2[3];
325 axis1[0] = o1->R[2];
326 axis1[1] = o1->R[6];
327 axis1[2] = o1->R[10];
328 axis2[0] = o2->R[2];
329 axis2[1] = o2->R[6];
330 axis2[2] = o2->R[10];
331
332 dReal alpha1,alpha2,sphere1[3],sphere2[3];
333 int fix1 = 0; // 0 if alpha1 is free, +/-1 to fix at +/- lz1
334 int fix2 = 0; // 0 if alpha2 is free, +/-1 to fix at +/- lz2
335
336 for (int count=0; count<9; count++) {
337 // find a trial solution by fixing or not fixing the alphas
338 if (fix1) {
339 if (fix2) {
340 // alpha1 and alpha2 are fixed, so the solution is easy
341 if (fix1 > 0) alpha1 = lz1; else alpha1 = -lz1;
342 if (fix2 > 0) alpha2 = lz2; else alpha2 = -lz2;
343 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
344 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
345 }
346 else {
347 // fix alpha1 but let alpha2 be free
348 if (fix1 > 0) alpha1 = lz1; else alpha1 = -lz1;
349 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
350 alpha2 = (axis2[0]*(sphere1[0]-pos2[0]) +
351 axis2[1]*(sphere1[1]-pos2[1]) +
352 axis2[2]*(sphere1[2]-pos2[2]));
353 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
354 }
355 }
356 else {
357 if (fix2) {
358 // fix alpha2 but let alpha1 be free
359 if (fix2 > 0) alpha2 = lz2; else alpha2 = -lz2;
360 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
361 alpha1 = (axis1[0]*(sphere2[0]-pos1[0]) +
362 axis1[1]*(sphere2[1]-pos1[1]) +
363 axis1[2]*(sphere2[2]-pos1[2]));
364 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
365 }
366 else {
367 // let alpha1 and alpha2 be free
368 // compute determinant of d(d^2)\d(alpha) jacobian
369 dReal a1a2 = dDOT (axis1,axis2);
370 dReal det = REAL(1.0)-a1a2*a1a2;
371 if (det < tolerance) {
372 // the cylinder axes (almost) parallel, so we will generate up to two
373 // contacts. the solution matrix is rank deficient so alpha1 and
374 // alpha2 are related by:
375 // alpha2 = alpha1 + (pos1-pos2)'*axis1 (if axis1==axis2)
376 // or alpha2 = -(alpha1 + (pos1-pos2)'*axis1) (if axis1==-axis2)
377 // first compute where the two cylinders overlap in alpha1 space:
378 if (a1a2 < 0) {
379 axis2[0] = -axis2[0];
380 axis2[1] = -axis2[1];
381 axis2[2] = -axis2[2];
382 }
383 dReal q[3];
384 for (i=0; i<3; i++) q[i] = pos1[i]-pos2[i];
385 dReal k = dDOT (axis1,q);
386 dReal a1lo = -lz1;
387 dReal a1hi = lz1;
388 dReal a2lo = -lz2 - k;
389 dReal a2hi = lz2 - k;
390 dReal lo = (a1lo > a2lo) ? a1lo : a2lo;
391 dReal hi = (a1hi < a2hi) ? a1hi : a2hi;
392 if (lo <= hi) {
393 int num_contacts = flags & NUMC_MASK;
394 if (num_contacts >= 2 && lo < hi) {
395 // generate up to two contacts. if one of those contacts is
396 // not made, fall back on the one-contact strategy.
397 for (i=0; i<3; i++) sphere1[i] = pos1[i] + lo*axis1[i];
398 for (i=0; i<3; i++) sphere2[i] = pos2[i] + (lo+k)*axis2[i];
399 int n1 = dCollideSpheres (sphere1,cyl1->radius,
400 sphere2,cyl2->radius,contact);
401 if (n1) {
402 for (i=0; i<3; i++) sphere1[i] = pos1[i] + hi*axis1[i];
403 for (i=0; i<3; i++) sphere2[i] = pos2[i] + (hi+k)*axis2[i];
404 dContactGeom *c2 = CONTACT(contact,skip);
405 int n2 = dCollideSpheres (sphere1,cyl1->radius,
406 sphere2,cyl2->radius, c2);
407 if (n2) {
408 c2->g1 = o1;
409 c2->g2 = o2;
410 return 2;
411 }
412 }
413 }
414
415 // just one contact to generate, so put it in the middle of
416 // the range
417 alpha1 = (lo + hi) * REAL(0.5);
418 alpha2 = alpha1 + k;
419 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
420 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
421 return dCollideSpheres (sphere1,cyl1->radius,
422 sphere2,cyl2->radius,contact);
423 }
424 else return 0;
425 }
426 det = REAL(1.0)/det;
427 dReal delta[3];
428 for (i=0; i<3; i++) delta[i] = pos1[i] - pos2[i];
429 dReal q1 = dDOT (delta,axis1);
430 dReal q2 = dDOT (delta,axis2);
431 alpha1 = det*(a1a2*q2-q1);
432 alpha2 = det*(q2-a1a2*q1);
433 for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
434 for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
435 }
436 }
437
438 // if the alphas are outside their allowed ranges then fix them and
439 // try again
440 if (fix1==0) {
441 if (alpha1 < -lz1) {
442 fix1 = -1;
443 continue;
444 }
445 if (alpha1 > lz1) {
446 fix1 = 1;
447 continue;
448 }
449 }
450 if (fix2==0) {
451 if (alpha2 < -lz2) {
452 fix2 = -1;
453 continue;
454 }
455 if (alpha2 > lz2) {
456 fix2 = 1;
457 continue;
458 }
459 }
460
461 // unfix the alpha variables if the local distance gradient indicates
462 // that we are not yet at the minimum
463 dReal tmp[3];
464 for (i=0; i<3; i++) tmp[i] = sphere1[i] - sphere2[i];
465 if (fix1) {
466 dReal gradient = dDOT (tmp,axis1);
467 if ((fix1 > 0 && gradient > 0) || (fix1 < 0 && gradient < 0)) {
468 fix1 = 0;
469 continue;
470 }
471 }
472 if (fix2) {
473 dReal gradient = -dDOT (tmp,axis2);
474 if ((fix2 > 0 && gradient > 0) || (fix2 < 0 && gradient < 0)) {
475 fix2 = 0;
476 continue;
477 }
478 }
479 return dCollideSpheres (sphere1,cyl1->radius,sphere2,cyl2->radius,contact);
480 }
481 // if we go through the loop too much, then give up. we should NEVER get to
482 // this point (i hope).
483 dMessage (0,"dCollideCC(): too many iterations");
484 return 0;
485}
diff --git a/libraries/ode-0.9/ode/src/sphere.cpp b/libraries/ode-0.9/ode/src/sphere.cpp
deleted file mode 100644
index fa25aac..0000000
--- a/libraries/ode-0.9/ode/src/sphere.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25standard ODE geometry primitives: public API and pairwise collision functions.
26
27the rule is that only the low level primitive collision functions should set
28dContactGeom::g1 and dContactGeom::g2.
29
30*/
31
32#include <ode/common.h>
33#include <ode/collision.h>
34#include <ode/matrix.h>
35#include <ode/rotation.h>
36#include <ode/odemath.h>
37#include "collision_kernel.h"
38#include "collision_std.h"
39#include "collision_util.h"
40
41#ifdef _MSC_VER
42#pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
43#endif
44
45
46//****************************************************************************
47// sphere public API
48
49dxSphere::dxSphere (dSpaceID space, dReal _radius) : dxGeom (space,1)
50{
51 dAASSERT (_radius > 0);
52 type = dSphereClass;
53 radius = _radius;
54}
55
56
57void dxSphere::computeAABB()
58{
59 aabb[0] = final_posr->pos[0] - radius;
60 aabb[1] = final_posr->pos[0] + radius;
61 aabb[2] = final_posr->pos[1] - radius;
62 aabb[3] = final_posr->pos[1] + radius;
63 aabb[4] = final_posr->pos[2] - radius;
64 aabb[5] = final_posr->pos[2] + radius;
65}
66
67
68dGeomID dCreateSphere (dSpaceID space, dReal radius)
69{
70 return new dxSphere (space,radius);
71}
72
73
74void dGeomSphereSetRadius (dGeomID g, dReal radius)
75{
76 dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
77 dAASSERT (radius > 0);
78 dxSphere *s = (dxSphere*) g;
79 s->radius = radius;
80 dGeomMoved (g);
81}
82
83
84dReal dGeomSphereGetRadius (dGeomID g)
85{
86 dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
87 dxSphere *s = (dxSphere*) g;
88 return s->radius;
89}
90
91
92dReal dGeomSpherePointDepth (dGeomID g, dReal x, dReal y, dReal z)
93{
94 dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
95 g->recomputePosr();
96
97 dxSphere *s = (dxSphere*) g;
98 dReal * pos = s->final_posr->pos;
99 return s->radius - dSqrt ((x-pos[0])*(x-pos[0]) +
100 (y-pos[1])*(y-pos[1]) +
101 (z-pos[2])*(z-pos[2]));
102}
103
104//****************************************************************************
105// pairwise collision functions for standard geom types
106
107int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags,
108 dContactGeom *contact, int skip)
109{
110 dIASSERT (skip >= (int)sizeof(dContactGeom));
111 dIASSERT (o1->type == dSphereClass);
112 dIASSERT (o2->type == dSphereClass);
113 dIASSERT ((flags & NUMC_MASK) >= 1);
114
115 dxSphere *sphere1 = (dxSphere*) o1;
116 dxSphere *sphere2 = (dxSphere*) o2;
117
118 contact->g1 = o1;
119 contact->g2 = o2;
120
121 return dCollideSpheres (o1->final_posr->pos,sphere1->radius,
122 o2->final_posr->pos,sphere2->radius,contact);
123}
124
125
126int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags,
127 dContactGeom *contact, int skip)
128{
129 dIASSERT (skip >= (int)sizeof(dContactGeom));
130 dIASSERT (o1->type == dSphereClass);
131 dIASSERT (o2->type == dBoxClass);
132 dIASSERT ((flags & NUMC_MASK) >= 1);
133
134 // this is easy. get the sphere center `p' relative to the box, and then clip
135 // that to the boundary of the box (call that point `q'). if q is on the
136 // boundary of the box and |p-q| is <= sphere radius, they touch.
137 // if q is inside the box, the sphere is inside the box, so set a contact
138 // normal to push the sphere to the closest box face.
139
140 dVector3 l,t,p,q,r;
141 dReal depth;
142 int onborder = 0;
143
144 dxSphere *sphere = (dxSphere*) o1;
145 dxBox *box = (dxBox*) o2;
146
147 contact->g1 = o1;
148 contact->g2 = o2;
149
150 p[0] = o1->final_posr->pos[0] - o2->final_posr->pos[0];
151 p[1] = o1->final_posr->pos[1] - o2->final_posr->pos[1];
152 p[2] = o1->final_posr->pos[2] - o2->final_posr->pos[2];
153
154 l[0] = box->side[0]*REAL(0.5);
155 t[0] = dDOT14(p,o2->final_posr->R);
156 if (t[0] < -l[0]) { t[0] = -l[0]; onborder = 1; }
157 if (t[0] > l[0]) { t[0] = l[0]; onborder = 1; }
158
159 l[1] = box->side[1]*REAL(0.5);
160 t[1] = dDOT14(p,o2->final_posr->R+1);
161 if (t[1] < -l[1]) { t[1] = -l[1]; onborder = 1; }
162 if (t[1] > l[1]) { t[1] = l[1]; onborder = 1; }
163
164 t[2] = dDOT14(p,o2->final_posr->R+2);
165 l[2] = box->side[2]*REAL(0.5);
166 if (t[2] < -l[2]) { t[2] = -l[2]; onborder = 1; }
167 if (t[2] > l[2]) { t[2] = l[2]; onborder = 1; }
168
169 if (!onborder) {
170 // sphere center inside box. find closest face to `t'
171 dReal min_distance = l[0] - dFabs(t[0]);
172 int mini = 0;
173 for (int i=1; i<3; i++) {
174 dReal face_distance = l[i] - dFabs(t[i]);
175 if (face_distance < min_distance) {
176 min_distance = face_distance;
177 mini = i;
178 }
179 }
180 // contact position = sphere center
181 contact->pos[0] = o1->final_posr->pos[0];
182 contact->pos[1] = o1->final_posr->pos[1];
183 contact->pos[2] = o1->final_posr->pos[2];
184 // contact normal points to closest face
185 dVector3 tmp;
186 tmp[0] = 0;
187 tmp[1] = 0;
188 tmp[2] = 0;
189 tmp[mini] = (t[mini] > 0) ? REAL(1.0) : REAL(-1.0);
190 dMULTIPLY0_331 (contact->normal,o2->final_posr->R,tmp);
191 // contact depth = distance to wall along normal plus radius
192 contact->depth = min_distance + sphere->radius;
193 return 1;
194 }
195
196 t[3] = 0; //@@@ hmmm
197 dMULTIPLY0_331 (q,o2->final_posr->R,t);
198 r[0] = p[0] - q[0];
199 r[1] = p[1] - q[1];
200 r[2] = p[2] - q[2];
201 depth = sphere->radius - dSqrt(dDOT(r,r));
202 if (depth < 0) return 0;
203 contact->pos[0] = q[0] + o2->final_posr->pos[0];
204 contact->pos[1] = q[1] + o2->final_posr->pos[1];
205 contact->pos[2] = q[2] + o2->final_posr->pos[2];
206 contact->normal[0] = r[0];
207 contact->normal[1] = r[1];
208 contact->normal[2] = r[2];
209 dNormalize3 (contact->normal);
210 contact->depth = depth;
211 return 1;
212}
213
214
215int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags,
216 dContactGeom *contact, int skip)
217{
218 dIASSERT (skip >= (int)sizeof(dContactGeom));
219 dIASSERT (o1->type == dSphereClass);
220 dIASSERT (o2->type == dPlaneClass);
221 dIASSERT ((flags & NUMC_MASK) >= 1);
222
223 dxSphere *sphere = (dxSphere*) o1;
224 dxPlane *plane = (dxPlane*) o2;
225
226 contact->g1 = o1;
227 contact->g2 = o2;
228 dReal k = dDOT (o1->final_posr->pos,plane->p);
229 dReal depth = plane->p[3] - k + sphere->radius;
230 if (depth >= 0) {
231 contact->normal[0] = plane->p[0];
232 contact->normal[1] = plane->p[1];
233 contact->normal[2] = plane->p[2];
234 contact->pos[0] = o1->final_posr->pos[0] - plane->p[0] * sphere->radius;
235 contact->pos[1] = o1->final_posr->pos[1] - plane->p[1] * sphere->radius;
236 contact->pos[2] = o1->final_posr->pos[2] - plane->p[2] * sphere->radius;
237 contact->depth = depth;
238 return 1;
239 }
240 else return 0;
241}
diff --git a/libraries/ode-0.9/ode/src/stack.cpp b/libraries/ode-0.9/ode/src/stack.cpp
deleted file mode 100644
index e062f92..0000000
--- a/libraries/ode-0.9/ode/src/stack.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23@@@ this file should not be compiled any more @@@
24
25#include <string.h>
26#include <errno.h>
27#include "stack.h"
28#include "ode/error.h"
29#include "ode/config.h"
30
31//****************************************************************************
32// unix version that uses mmap(). some systems have anonymous mmaps and some
33// need to mmap /dev/zero.
34
35#ifndef WIN32
36
37#include <unistd.h>
38#include <sys/mman.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42
43
44void dStack::init (int max_size)
45{
46 if (sizeof(long int) != sizeof(char*)) dDebug (0,"internal");
47 if (max_size <= 0) dDebug (0,"Stack::init() given size <= 0");
48
49#ifndef MMAP_ANONYMOUS
50 static int dev_zero_fd = -1; // cached file descriptor for /dev/zero
51 if (dev_zero_fd < 0) dev_zero_fd = open ("/dev/zero", O_RDWR);
52 if (dev_zero_fd < 0) dError (0,"can't open /dev/zero (%s)",strerror(errno));
53 base = (char*) mmap (0,max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
54 dev_zero_fd,0);
55#else
56 base = (char*) mmap (0,max_size, PROT_READ | PROT_WRITE,
57 MAP_PRIVATE | MAP_ANON,0,0);
58#endif
59
60 if (int(base) == -1) dError (0,"Stack::init(), mmap() failed, "
61 "max_size=%d (%s)",max_size,strerror(errno));
62 size = max_size;
63 pointer = base;
64 frame = 0;
65}
66
67
68void dStack::destroy()
69{
70 munmap (base,size);
71 base = 0;
72 size = 0;
73 pointer = 0;
74 frame = 0;
75}
76
77#endif
78
79//****************************************************************************
80
81#ifdef WIN32
82
83#include "windows.h"
84
85
86void dStack::init (int max_size)
87{
88 if (sizeof(LPVOID) != sizeof(char*)) dDebug (0,"internal");
89 if (max_size <= 0) dDebug (0,"Stack::init() given size <= 0");
90 base = (char*) VirtualAlloc (NULL,max_size,MEM_RESERVE,PAGE_READWRITE);
91 if (base == 0) dError (0,"Stack::init(), VirtualAlloc() failed, "
92 "max_size=%d",max_size);
93 size = max_size;
94 pointer = base;
95 frame = 0;
96 committed = 0;
97
98 // get page size
99 SYSTEM_INFO info;
100 GetSystemInfo (&info);
101 pagesize = info.dwPageSize;
102}
103
104
105void dStack::destroy()
106{
107 VirtualFree (base,0,MEM_RELEASE);
108 base = 0;
109 size = 0;
110 pointer = 0;
111 frame = 0;
112}
113
114#endif
diff --git a/libraries/ode-0.9/ode/src/stack.h b/libraries/ode-0.9/ode/src/stack.h
deleted file mode 100644
index 5afff41..0000000
--- a/libraries/ode-0.9/ode/src/stack.h
+++ /dev/null
@@ -1,138 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/* this comes from the `reuse' library. copy any changes back to the source.
24
25these stack allocation functions are a replacement for alloca(), except that
26they allocate memory from a separate pool.
27
28advantages over alloca():
29 - consecutive allocations are guaranteed to be contiguous with increasing
30 address.
31 - functions can allocate stack memory that is returned to the caller,
32 in other words pushing and popping stack frames is optional.
33
34disadvantages compared to alloca():
35 - less portable
36 - slightly slower, although still orders of magnitude faster than malloc().
37 - longjmp() and exceptions do not deallocate stack memory (but who cares?).
38
39just like alloca():
40 - using too much stack memory does not fail gracefully, it fails with a
41 segfault.
42
43*/
44
45
46#ifndef _ODE_STACK_H_
47#define _ODE_STACK_H_
48
49
50#ifdef WIN32
51#include "windows.h"
52#endif
53
54
55struct dStack {
56 char *base; // bottom of the stack
57 int size; // maximum size of the stack
58 char *pointer; // current top of the stack
59 char *frame; // linked list of stack frame ptrs
60# ifdef WIN32 // stuff for windows:
61 int pagesize; // - page size - this is ASSUMED to be a power of 2
62 int committed; // - bytes committed in allocated region
63#endif
64
65 // initialize the stack. `max_size' is the maximum size that the stack can
66 // reach. on unix and windows a `virtual' memory block of this size is
67 // mapped into the address space but does not actually consume physical
68 // memory until it is referenced - so it is safe to set this to a high value.
69
70 void init (int max_size);
71
72
73 // destroy the stack. this unmaps any virtual memory that was allocated.
74
75 void destroy();
76
77
78 // allocate `size' bytes from the stack and return a pointer to the allocated
79 // memory. `size' must be >= 0. the returned pointer will be aligned to the
80 // size of a long int.
81
82 char * alloc (int size)
83 {
84 char *ret = pointer;
85 pointer += ((size-1) | (sizeof(long int)-1) )+1;
86# ifdef WIN32
87 // for windows we need to commit pages as they are required
88 if ((pointer-base) > committed) {
89 committed = ((pointer-base-1) | (pagesize-1))+1; // round up to pgsize
90 VirtualAlloc (base,committed,MEM_COMMIT,PAGE_READWRITE);
91 }
92# endif
93 return ret;
94 }
95
96
97 // return the address that will be returned by the next call to alloc()
98
99 char *nextAlloc()
100 {
101 return pointer;
102 }
103
104
105 // push and pop the current size of the stack. pushFrame() saves the current
106 // frame pointer on the stack, and popFrame() retrieves it. a typical
107 // stack-using function will bracket alloc() calls with pushFrame() and
108 // popFrame(). both functions return the current stack pointer - this should
109 // be the same value for the two bracketing calls. calling popFrame() too
110 // many times will result in a segfault.
111
112 char * pushFrame()
113 {
114 char *newframe = pointer;
115 char **addr = (char**) alloc (sizeof(char*));
116 *addr = frame;
117 frame = newframe;
118 return newframe;
119
120 /* OLD CODE
121 *((char**)pointer) = frame;
122 frame = pointer;
123 char *ret = pointer;
124 pointer += sizeof(char*);
125 return ret;
126 */
127 }
128
129 char * popFrame()
130 {
131 pointer = frame;
132 frame = *((char**)pointer);
133 return pointer;
134 }
135};
136
137
138#endif
diff --git a/libraries/ode-0.9/ode/src/step.cpp b/libraries/ode-0.9/ode/src/step.cpp
deleted file mode 100644
index 19d0473..0000000
--- a/libraries/ode-0.9/ode/src/step.cpp
+++ /dev/null
@@ -1,1795 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include "objects.h"
24#include "joint.h"
25#include <ode/config.h>
26#include <ode/odemath.h>
27#include <ode/rotation.h>
28#include <ode/timer.h>
29#include <ode/error.h>
30#include <ode/matrix.h>
31#include "lcp.h"
32#include "util.h"
33
34//****************************************************************************
35// misc defines
36
37#define FAST_FACTOR
38//#define TIMING
39
40// memory allocation system
41#ifdef dUSE_MALLOC_FOR_ALLOCA
42unsigned int dMemoryFlag;
43#define REPORT_OUT_OF_MEMORY fprintf(stderr, "Insufficient memory to complete rigid body simulation. Results will not be accurate.\n")
44
45#define ALLOCA(t,v,s) t* v=(t*)malloc(s)
46#define UNALLOCA(t) free(t)
47
48#else
49#define ALLOCA(t,v,s) t* v=(t*)dALLOCA16(s)
50#define UNALLOCA(t) /* nothing */
51#endif
52
53
54//****************************************************************************
55// debugging - comparison of various vectors and matrices produced by the
56// slow and fast versions of the stepper.
57
58//#define COMPARE_METHODS
59
60#ifdef COMPARE_METHODS
61#include "testing.h"
62dMatrixComparison comparator;
63#endif
64
65// undef to use the fast decomposition
66#define DIRECT_CHOLESKY
67#undef REPORT_ERROR
68
69//****************************************************************************
70// special matrix multipliers
71
72// this assumes the 4th and 8th rows of B and C are zero.
73
74static void Multiply2_p8r (dReal *A, dReal *B, dReal *C,
75 int p, int r, int Askip)
76{
77 int i,j;
78 dReal sum,*bb,*cc;
79 dIASSERT (p>0 && r>0 && A && B && C);
80 bb = B;
81 for (i=p; i; i--) {
82 cc = C;
83 for (j=r; j; j--) {
84 sum = bb[0]*cc[0];
85 sum += bb[1]*cc[1];
86 sum += bb[2]*cc[2];
87 sum += bb[4]*cc[4];
88 sum += bb[5]*cc[5];
89 sum += bb[6]*cc[6];
90 *(A++) = sum;
91 cc += 8;
92 }
93 A += Askip - r;
94 bb += 8;
95 }
96}
97
98
99// this assumes the 4th and 8th rows of B and C are zero.
100
101static void MultiplyAdd2_p8r (dReal *A, dReal *B, dReal *C,
102 int p, int r, int Askip)
103{
104 int i,j;
105 dReal sum,*bb,*cc;
106 dIASSERT (p>0 && r>0 && A && B && C);
107 bb = B;
108 for (i=p; i; i--) {
109 cc = C;
110 for (j=r; j; j--) {
111 sum = bb[0]*cc[0];
112 sum += bb[1]*cc[1];
113 sum += bb[2]*cc[2];
114 sum += bb[4]*cc[4];
115 sum += bb[5]*cc[5];
116 sum += bb[6]*cc[6];
117 *(A++) += sum;
118 cc += 8;
119 }
120 A += Askip - r;
121 bb += 8;
122 }
123}
124
125
126// this assumes the 4th and 8th rows of B are zero.
127
128static void Multiply0_p81 (dReal *A, dReal *B, dReal *C, int p)
129{
130 int i;
131 dIASSERT (p>0 && A && B && C);
132 dReal sum;
133 for (i=p; i; i--) {
134 sum = B[0]*C[0];
135 sum += B[1]*C[1];
136 sum += B[2]*C[2];
137 sum += B[4]*C[4];
138 sum += B[5]*C[5];
139 sum += B[6]*C[6];
140 *(A++) = sum;
141 B += 8;
142 }
143}
144
145
146// this assumes the 4th and 8th rows of B are zero.
147
148static void MultiplyAdd0_p81 (dReal *A, dReal *B, dReal *C, int p)
149{
150 int i;
151 dIASSERT (p>0 && A && B && C);
152 dReal sum;
153 for (i=p; i; i--) {
154 sum = B[0]*C[0];
155 sum += B[1]*C[1];
156 sum += B[2]*C[2];
157 sum += B[4]*C[4];
158 sum += B[5]*C[5];
159 sum += B[6]*C[6];
160 *(A++) += sum;
161 B += 8;
162 }
163}
164
165
166// this assumes the 4th and 8th rows of B are zero.
167
168static void MultiplyAdd1_8q1 (dReal *A, dReal *B, dReal *C, int q)
169{
170 int k;
171 dReal sum;
172 dIASSERT (q>0 && A && B && C);
173 sum = 0;
174 for (k=0; k<q; k++) sum += B[k*8] * C[k];
175 A[0] += sum;
176 sum = 0;
177 for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
178 A[1] += sum;
179 sum = 0;
180 for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
181 A[2] += sum;
182 sum = 0;
183 for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
184 A[4] += sum;
185 sum = 0;
186 for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
187 A[5] += sum;
188 sum = 0;
189 for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
190 A[6] += sum;
191}
192
193
194// this assumes the 4th and 8th rows of B are zero.
195
196static void Multiply1_8q1 (dReal *A, dReal *B, dReal *C, int q)
197{
198 int k;
199 dReal sum;
200 dIASSERT (q>0 && A && B && C);
201 sum = 0;
202 for (k=0; k<q; k++) sum += B[k*8] * C[k];
203 A[0] = sum;
204 sum = 0;
205 for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
206 A[1] = sum;
207 sum = 0;
208 for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
209 A[2] = sum;
210 sum = 0;
211 for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
212 A[4] = sum;
213 sum = 0;
214 for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
215 A[5] = sum;
216 sum = 0;
217 for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
218 A[6] = sum;
219}
220
221//****************************************************************************
222// the slow, but sure way
223// note that this does not do any joint feedback!
224
225// given lists of bodies and joints that form an island, perform a first
226// order timestep.
227//
228// `body' is the body array, `nb' is the size of the array.
229// `_joint' is the body array, `nj' is the size of the array.
230
231void dInternalStepIsland_x1 (dxWorld *world, dxBody * const *body, int nb,
232 dxJoint * const *_joint, int nj, dReal stepsize)
233{
234 int i,j,k;
235 int n6 = 6*nb;
236
237#ifdef TIMING
238 dTimerStart("preprocessing");
239#endif
240
241 // number all bodies in the body list - set their tag values
242 for (i=0; i<nb; i++) body[i]->tag = i;
243
244 // make a local copy of the joint array, because we might want to modify it.
245 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
246 // but not the joint array, because the caller might need it unchanged).
247 ALLOCA(dxJoint*,joint,nj*sizeof(dxJoint*));
248#ifdef dUSE_MALLOC_FOR_ALLOCA
249 if (joint == NULL) {
250 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
251 return;
252 }
253#endif
254 memcpy (joint,_joint,nj * sizeof(dxJoint*));
255
256 // for all bodies, compute the inertia tensor and its inverse in the global
257 // frame, and compute the rotational force and add it to the torque
258 // accumulator.
259 // @@@ check computation of rotational force.
260 ALLOCA(dReal,I,3*nb*4*sizeof(dReal));
261#ifdef dUSE_MALLOC_FOR_ALLOCA
262 if (I == NULL) {
263 UNALLOCA(joint);
264 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
265 return;
266 }
267#endif
268 ALLOCA(dReal,invI,3*nb*4*sizeof(dReal));
269#ifdef dUSE_MALLOC_FOR_ALLOCA
270 if (invI == NULL) {
271 UNALLOCA(I);
272 UNALLOCA(joint);
273 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
274 return;
275 }
276#endif
277
278 //dSetZero (I,3*nb*4);
279 //dSetZero (invI,3*nb*4);
280 for (i=0; i<nb; i++) {
281 dReal tmp[12];
282 // compute inertia tensor in global frame
283 dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
284 dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
285 // compute inverse inertia tensor in global frame
286 dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
287 dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
288 // compute rotational force
289 dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
290 dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
291 }
292
293 // add the gravity force to all bodies
294 for (i=0; i<nb; i++) {
295 if ((body[i]->flags & dxBodyNoGravity)==0) {
296 body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
297 body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
298 body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
299 }
300 }
301
302 // get m = total constraint dimension, nub = number of unbounded variables.
303 // create constraint offset array and number-of-rows array for all joints.
304 // the constraints are re-ordered as follows: the purely unbounded
305 // constraints, the mixed unbounded + LCP constraints, and last the purely
306 // LCP constraints.
307 //
308 // joints with m=0 are inactive and are removed from the joints array
309 // entirely, so that the code that follows does not consider them.
310 int m = 0;
311 ALLOCA(dxJoint::Info1,info,nj*sizeof(dxJoint::Info1));
312#ifdef dUSE_MALLOC_FOR_ALLOCA
313 if (info == NULL) {
314 UNALLOCA(invI);
315 UNALLOCA(I);
316 UNALLOCA(joint);
317 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
318 return;
319 }
320#endif
321
322 ALLOCA(int,ofs,nj*sizeof(int));
323#ifdef dUSE_MALLOC_FOR_ALLOCA
324 if (ofs == NULL) {
325 UNALLOCA(info);
326 UNALLOCA(invI);
327 UNALLOCA(I);
328 UNALLOCA(joint);
329 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
330 return;
331 }
332#endif
333
334 for (i=0, j=0; j<nj; j++) { // i=dest, j=src
335 joint[j]->vtable->getInfo1 (joint[j],info+i);
336 dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
337 info[i].nub >= 0 && info[i].nub <= info[i].m);
338 if (info[i].m > 0) {
339 joint[i] = joint[j];
340 i++;
341 }
342 }
343 nj = i;
344
345 // the purely unbounded constraints
346 for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
347 ofs[i] = m;
348 m += info[i].m;
349 }
350 int nub = m;
351 // the mixed unbounded + LCP constraints
352 for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
353 ofs[i] = m;
354 m += info[i].m;
355 }
356 // the purely LCP constraints
357 for (i=0; i<nj; i++) if (info[i].nub == 0) {
358 ofs[i] = m;
359 m += info[i].m;
360 }
361
362 // create (6*nb,6*nb) inverse mass matrix `invM', and fill it with mass
363 // parameters
364#ifdef TIMING
365 dTimerNow ("create mass matrix");
366#endif
367 int nskip = dPAD (n6);
368 ALLOCA(dReal, invM, n6*nskip*sizeof(dReal));
369#ifdef dUSE_MALLOC_FOR_ALLOCA
370 if (invM == NULL) {
371 UNALLOCA(ofs);
372 UNALLOCA(info);
373 UNALLOCA(invI);
374 UNALLOCA(I);
375 UNALLOCA(joint);
376 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
377 return;
378 }
379#endif
380
381 dSetZero (invM,n6*nskip);
382 for (i=0; i<nb; i++) {
383 dReal *MM = invM+(i*6)*nskip+(i*6);
384 MM[0] = body[i]->invMass;
385 MM[nskip+1] = body[i]->invMass;
386 MM[2*nskip+2] = body[i]->invMass;
387 MM += 3*nskip+3;
388 for (j=0; j<3; j++) for (k=0; k<3; k++) {
389 MM[j*nskip+k] = invI[i*12+j*4+k];
390 }
391 }
392
393 // assemble some body vectors: fe = external forces, v = velocities
394 ALLOCA(dReal,fe,n6*sizeof(dReal));
395#ifdef dUSE_MALLOC_FOR_ALLOCA
396 if (fe == NULL) {
397 UNALLOCA(invM);
398 UNALLOCA(ofs);
399 UNALLOCA(info);
400 UNALLOCA(invI);
401 UNALLOCA(I);
402 UNALLOCA(joint);
403 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
404 return;
405 }
406#endif
407
408 ALLOCA(dReal,v,n6*sizeof(dReal));
409#ifdef dUSE_MALLOC_FOR_ALLOCA
410 if (v == NULL) {
411 UNALLOCA(fe);
412 UNALLOCA(invM);
413 UNALLOCA(ofs);
414 UNALLOCA(info);
415 UNALLOCA(invI);
416 UNALLOCA(I);
417 UNALLOCA(joint);
418 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
419 return;
420 }
421#endif
422
423 //dSetZero (fe,n6);
424 //dSetZero (v,n6);
425 for (i=0; i<nb; i++) {
426 for (j=0; j<3; j++) fe[i*6+j] = body[i]->facc[j];
427 for (j=0; j<3; j++) fe[i*6+3+j] = body[i]->tacc[j];
428 for (j=0; j<3; j++) v[i*6+j] = body[i]->lvel[j];
429 for (j=0; j<3; j++) v[i*6+3+j] = body[i]->avel[j];
430 }
431
432 // this will be set to the velocity update
433 ALLOCA(dReal,vnew,n6*sizeof(dReal));
434#ifdef dUSE_MALLOC_FOR_ALLOCA
435 if (vnew == NULL) {
436 UNALLOCA(v);
437 UNALLOCA(fe);
438 UNALLOCA(invM);
439 UNALLOCA(ofs);
440 UNALLOCA(info);
441 UNALLOCA(invI);
442 UNALLOCA(I);
443 UNALLOCA(joint);
444 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
445 return;
446 }
447#endif
448 dSetZero (vnew,n6);
449
450 // if there are constraints, compute cforce
451 if (m > 0) {
452 // create a constraint equation right hand side vector `c', a constraint
453 // force mixing vector `cfm', and LCP low and high bound vectors, and an
454 // 'findex' vector.
455 ALLOCA(dReal,c,m*sizeof(dReal));
456#ifdef dUSE_MALLOC_FOR_ALLOCA
457 if (c == NULL) {
458 UNALLOCA(vnew);
459 UNALLOCA(v);
460 UNALLOCA(fe);
461 UNALLOCA(invM);
462 UNALLOCA(ofs);
463 UNALLOCA(info);
464 UNALLOCA(invI);
465 UNALLOCA(I);
466 UNALLOCA(joint);
467 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
468 return;
469 }
470#endif
471 ALLOCA(dReal,cfm,m*sizeof(dReal));
472#ifdef dUSE_MALLOC_FOR_ALLOCA
473 if (cfm == NULL) {
474 UNALLOCA(c);
475 UNALLOCA(vnew);
476 UNALLOCA(v);
477 UNALLOCA(fe);
478 UNALLOCA(invM);
479 UNALLOCA(ofs);
480 UNALLOCA(info);
481 UNALLOCA(invI);
482 UNALLOCA(I);
483 UNALLOCA(joint);
484 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
485 return;
486 }
487#endif
488 ALLOCA(dReal,lo,m*sizeof(dReal));
489#ifdef dUSE_MALLOC_FOR_ALLOCA
490 if (lo == NULL) {
491 UNALLOCA(cfm);
492 UNALLOCA(c);
493 UNALLOCA(vnew);
494 UNALLOCA(v);
495 UNALLOCA(fe);
496 UNALLOCA(invM);
497 UNALLOCA(ofs);
498 UNALLOCA(info);
499 UNALLOCA(invI);
500 UNALLOCA(I);
501 UNALLOCA(joint);
502 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
503 return;
504 }
505#endif
506 ALLOCA(dReal,hi,m*sizeof(dReal));
507#ifdef dUSE_MALLOC_FOR_ALLOCA
508 if (hi == NULL) {
509 UNALLOCA(lo);
510 UNALLOCA(cfm);
511 UNALLOCA(c);
512 UNALLOCA(vnew);
513 UNALLOCA(v);
514 UNALLOCA(fe);
515 UNALLOCA(invM);
516 UNALLOCA(ofs);
517 UNALLOCA(info);
518 UNALLOCA(invI);
519 UNALLOCA(I);
520 UNALLOCA(joint);
521 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
522 return;
523 }
524#endif
525 ALLOCA(int,findex,m*sizeof(int));
526#ifdef dUSE_MALLOC_FOR_ALLOCA
527 if (findex == NULL) {
528 UNALLOCA(hi);
529 UNALLOCA(lo);
530 UNALLOCA(cfm);
531 UNALLOCA(c);
532 UNALLOCA(vnew);
533 UNALLOCA(v);
534 UNALLOCA(fe);
535 UNALLOCA(invM);
536 UNALLOCA(ofs);
537 UNALLOCA(info);
538 UNALLOCA(invI);
539 UNALLOCA(I);
540 UNALLOCA(joint);
541 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
542 return;
543 }
544#endif
545 dSetZero (c,m);
546 dSetValue (cfm,m,world->global_cfm);
547 dSetValue (lo,m,-dInfinity);
548 dSetValue (hi,m, dInfinity);
549 for (i=0; i<m; i++) findex[i] = -1;
550
551 // create (m,6*nb) jacobian mass matrix `J', and fill it with constraint
552 // data. also fill the c vector.
553# ifdef TIMING
554 dTimerNow ("create J");
555# endif
556 ALLOCA(dReal,J,m*nskip*sizeof(dReal));
557#ifdef dUSE_MALLOC_FOR_ALLOCA
558 if (J == NULL) {
559 UNALLOCA(findex);
560 UNALLOCA(hi);
561 UNALLOCA(lo);
562 UNALLOCA(cfm);
563 UNALLOCA(c);
564 UNALLOCA(vnew);
565 UNALLOCA(v);
566 UNALLOCA(fe);
567 UNALLOCA(invM);
568 UNALLOCA(ofs);
569 UNALLOCA(info);
570 UNALLOCA(invI);
571 UNALLOCA(I);
572 UNALLOCA(joint);
573 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
574 return;
575 }
576#endif
577 dSetZero (J,m*nskip);
578 dxJoint::Info2 Jinfo;
579 Jinfo.rowskip = nskip;
580 Jinfo.fps = dRecip(stepsize);
581 Jinfo.erp = world->global_erp;
582 for (i=0; i<nj; i++) {
583 Jinfo.J1l = J + nskip*ofs[i] + 6*joint[i]->node[0].body->tag;
584 Jinfo.J1a = Jinfo.J1l + 3;
585 if (joint[i]->node[1].body) {
586 Jinfo.J2l = J + nskip*ofs[i] + 6*joint[i]->node[1].body->tag;
587 Jinfo.J2a = Jinfo.J2l + 3;
588 }
589 else {
590 Jinfo.J2l = 0;
591 Jinfo.J2a = 0;
592 }
593 Jinfo.c = c + ofs[i];
594 Jinfo.cfm = cfm + ofs[i];
595 Jinfo.lo = lo + ofs[i];
596 Jinfo.hi = hi + ofs[i];
597 Jinfo.findex = findex + ofs[i];
598 joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
599 // adjust returned findex values for global index numbering
600 for (j=0; j<info[i].m; j++) {
601 if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
602 }
603 }
604
605 // compute A = J*invM*J'
606# ifdef TIMING
607 dTimerNow ("compute A");
608# endif
609 ALLOCA(dReal,JinvM,m*nskip*sizeof(dReal));
610#ifdef dUSE_MALLOC_FOR_ALLOCA
611 if (JinvM == NULL) {
612 UNALLOCA(J);
613 UNALLOCA(findex);
614 UNALLOCA(hi);
615 UNALLOCA(lo);
616 UNALLOCA(cfm);
617 UNALLOCA(c);
618 UNALLOCA(vnew);
619 UNALLOCA(v);
620 UNALLOCA(fe);
621 UNALLOCA(invM);
622 UNALLOCA(ofs);
623 UNALLOCA(info);
624 UNALLOCA(invI);
625 UNALLOCA(I);
626 UNALLOCA(joint);
627 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
628 return;
629 }
630#endif
631 //dSetZero (JinvM,m*nskip);
632 dMultiply0 (JinvM,J,invM,m,n6,n6);
633 int mskip = dPAD(m);
634 ALLOCA(dReal,A,m*mskip*sizeof(dReal));
635#ifdef dUSE_MALLOC_FOR_ALLOCA
636 if (A == NULL) {
637 UNALLOCA(JinvM);
638 UNALLOCA(J);
639 UNALLOCA(findex);
640 UNALLOCA(hi);
641 UNALLOCA(lo);
642 UNALLOCA(cfm);
643 UNALLOCA(c);
644 UNALLOCA(vnew);
645 UNALLOCA(v);
646 UNALLOCA(fe);
647 UNALLOCA(invM);
648 UNALLOCA(ofs);
649 UNALLOCA(info);
650 UNALLOCA(invI);
651 UNALLOCA(I);
652 UNALLOCA(joint);
653 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
654 return;
655 }
656#endif
657 //dSetZero (A,m*mskip);
658 dMultiply2 (A,JinvM,J,m,n6,m);
659
660 // add cfm to the diagonal of A
661 for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * Jinfo.fps;
662
663# ifdef COMPARE_METHODS
664 comparator.nextMatrix (A,m,m,1,"A");
665# endif
666
667 // compute `rhs', the right hand side of the equation J*a=c
668# ifdef TIMING
669 dTimerNow ("compute rhs");
670# endif
671 ALLOCA(dReal,tmp1,n6*sizeof(dReal));
672#ifdef dUSE_MALLOC_FOR_ALLOCA
673 if (tmp1 == NULL) {
674 UNALLOCA(A);
675 UNALLOCA(JinvM);
676 UNALLOCA(J);
677 UNALLOCA(findex);
678 UNALLOCA(hi);
679 UNALLOCA(lo);
680 UNALLOCA(cfm);
681 UNALLOCA(c);
682 UNALLOCA(vnew);
683 UNALLOCA(v);
684 UNALLOCA(fe);
685 UNALLOCA(invM);
686 UNALLOCA(ofs);
687 UNALLOCA(info);
688 UNALLOCA(invI);
689 UNALLOCA(I);
690 UNALLOCA(joint);
691 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
692 return;
693 }
694#endif
695 //dSetZero (tmp1,n6);
696 dMultiply0 (tmp1,invM,fe,n6,n6,1);
697 for (i=0; i<n6; i++) tmp1[i] += v[i]/stepsize;
698 ALLOCA(dReal,rhs,m*sizeof(dReal));
699#ifdef dUSE_MALLOC_FOR_ALLOCA
700 if (rhs == NULL) {
701 UNALLOCA(tmp1);
702 UNALLOCA(A);
703 UNALLOCA(JinvM);
704 UNALLOCA(J);
705 UNALLOCA(findex);
706 UNALLOCA(hi);
707 UNALLOCA(lo);
708 UNALLOCA(cfm);
709 UNALLOCA(c);
710 UNALLOCA(vnew);
711 UNALLOCA(v);
712 UNALLOCA(fe);
713 UNALLOCA(invM);
714 UNALLOCA(ofs);
715 UNALLOCA(info);
716 UNALLOCA(invI);
717 UNALLOCA(I);
718 UNALLOCA(joint);
719 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
720 return;
721 }
722#endif
723 //dSetZero (rhs,m);
724 dMultiply0 (rhs,J,tmp1,m,n6,1);
725 for (i=0; i<m; i++) rhs[i] = c[i]/stepsize - rhs[i];
726
727# ifdef COMPARE_METHODS
728 comparator.nextMatrix (c,m,1,0,"c");
729 comparator.nextMatrix (rhs,m,1,0,"rhs");
730# endif
731
732
733
734
735
736#ifndef DIRECT_CHOLESKY
737 // solve the LCP problem and get lambda.
738 // this will destroy A but that's okay
739# ifdef TIMING
740 dTimerNow ("solving LCP problem");
741# endif
742 ALLOCA(dReal,lambda,m*sizeof(dReal));
743#ifdef dUSE_MALLOC_FOR_ALLOCA
744 if (lambda == NULL) {
745 UNALLOCA(rhs);
746 UNALLOCA(tmp1);
747 UNALLOCA(A);
748 UNALLOCA(JinvM);
749 UNALLOCA(J);
750 UNALLOCA(findex);
751 UNALLOCA(hi);
752 UNALLOCA(lo);
753 UNALLOCA(cfm);
754 UNALLOCA(c);
755 UNALLOCA(vnew);
756 UNALLOCA(v);
757 UNALLOCA(fe);
758 UNALLOCA(invM);
759 UNALLOCA(ofs);
760 UNALLOCA(info);
761 UNALLOCA(invI);
762 UNALLOCA(I);
763 UNALLOCA(joint);
764 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
765 return;
766 }
767#endif
768 ALLOCA(dReal,residual,m*sizeof(dReal));
769#ifdef dUSE_MALLOC_FOR_ALLOCA
770 if (residual == NULL) {
771 UNALLOCA(lambda);
772 UNALLOCA(rhs);
773 UNALLOCA(tmp1);
774 UNALLOCA(A);
775 UNALLOCA(JinvM);
776 UNALLOCA(J);
777 UNALLOCA(findex);
778 UNALLOCA(hi);
779 UNALLOCA(lo);
780 UNALLOCA(cfm);
781 UNALLOCA(c);
782 UNALLOCA(vnew);
783 UNALLOCA(v);
784 UNALLOCA(fe);
785 UNALLOCA(invM);
786 UNALLOCA(ofs);
787 UNALLOCA(info);
788 UNALLOCA(invI);
789 UNALLOCA(I);
790 UNALLOCA(joint);
791 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
792 return;
793 }
794#endif
795 dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
796 UNALLOCA(residual);
797 UNALLOCA(lambda);
798
799#ifdef dUSE_MALLOC_FOR_ALLOCA
800 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
801 return;
802#endif
803
804
805#else
806
807 // OLD WAY - direct factor and solve
808
809 // factorize A (L*L'=A)
810# ifdef TIMING
811 dTimerNow ("factorize A");
812# endif
813 ALLOCA(dReal,L,m*mskip*sizeof(dReal));
814#ifdef dUSE_MALLOC_FOR_ALLOCA
815 if (L == NULL) {
816 UNALLOCA(rhs);
817 UNALLOCA(tmp1);
818 UNALLOCA(A);
819 UNALLOCA(JinvM);
820 UNALLOCA(J);
821 UNALLOCA(findex);
822 UNALLOCA(hi);
823 UNALLOCA(lo);
824 UNALLOCA(cfm);
825 UNALLOCA(c);
826 UNALLOCA(vnew);
827 UNALLOCA(v);
828 UNALLOCA(fe);
829 UNALLOCA(invM);
830 UNALLOCA(ofs);
831 UNALLOCA(info);
832 UNALLOCA(invI);
833 UNALLOCA(I);
834 UNALLOCA(joint);
835 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
836 return;
837 }
838#endif
839 memcpy (L,A,m*mskip*sizeof(dReal));
840 if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
841
842 // compute lambda
843# ifdef TIMING
844 dTimerNow ("compute lambda");
845# endif
846 ALLOCA(dReal,lambda,m*sizeof(dReal));
847#ifdef dUSE_MALLOC_FOR_ALLOCA
848 if (lambda == NULL) {
849 UNALLOCA(L);
850 UNALLOCA(rhs);
851 UNALLOCA(tmp1);
852 UNALLOCA(A);
853 UNALLOCA(JinvM);
854 UNALLOCA(J);
855 UNALLOCA(findex);
856 UNALLOCA(hi);
857 UNALLOCA(lo);
858 UNALLOCA(cfm);
859 UNALLOCA(c);
860 UNALLOCA(vnew);
861 UNALLOCA(v);
862 UNALLOCA(fe);
863 UNALLOCA(invM);
864 UNALLOCA(ofs);
865 UNALLOCA(info);
866 UNALLOCA(invI);
867 UNALLOCA(I);
868 UNALLOCA(joint);
869 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
870 return;
871 }
872#endif
873 memcpy (lambda,rhs,m * sizeof(dReal));
874 dSolveCholesky (L,lambda,m);
875#endif
876
877# ifdef COMPARE_METHODS
878 comparator.nextMatrix (lambda,m,1,0,"lambda");
879# endif
880
881 // compute the velocity update `vnew'
882# ifdef TIMING
883 dTimerNow ("compute velocity update");
884# endif
885 dMultiply1 (tmp1,J,lambda,n6,m,1);
886 for (i=0; i<n6; i++) tmp1[i] += fe[i];
887 dMultiply0 (vnew,invM,tmp1,n6,n6,1);
888 for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
889
890#ifdef REPORT_ERROR
891 // see if the constraint has worked: compute J*vnew and make sure it equals
892 // `c' (to within a certain tolerance).
893# ifdef TIMING
894 dTimerNow ("verify constraint equation");
895# endif
896 dMultiply0 (tmp1,J,vnew,m,n6,1);
897 dReal err = 0;
898 for (i=0; i<m; i++) {
899 err += dFabs(tmp1[i]-c[i]);
900 }
901 printf ("total constraint error=%.6e\n",err);
902#endif
903
904 UNALLOCA(c);
905 UNALLOCA(cfm);
906 UNALLOCA(lo);
907 UNALLOCA(hi);
908 UNALLOCA(findex);
909 UNALLOCA(J);
910 UNALLOCA(JinvM);
911 UNALLOCA(A);
912 UNALLOCA(tmp1);
913 UNALLOCA(rhs);
914 UNALLOCA(lambda);
915 UNALLOCA(L);
916 }
917 else {
918 // no constraints
919 dMultiply0 (vnew,invM,fe,n6,n6,1);
920 for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
921 }
922
923#ifdef COMPARE_METHODS
924 comparator.nextMatrix (vnew,n6,1,0,"vnew");
925#endif
926
927 // apply the velocity update to the bodies
928#ifdef TIMING
929 dTimerNow ("update velocity");
930#endif
931 for (i=0; i<nb; i++) {
932 for (j=0; j<3; j++) body[i]->lvel[j] = vnew[i*6+j];
933 for (j=0; j<3; j++) body[i]->avel[j] = vnew[i*6+3+j];
934 }
935
936 // update the position and orientation from the new linear/angular velocity
937 // (over the given timestep)
938#ifdef TIMING
939 dTimerNow ("update position");
940#endif
941 for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
942
943#ifdef TIMING
944 dTimerNow ("tidy up");
945#endif
946
947 // zero all force accumulators
948 for (i=0; i<nb; i++) {
949 body[i]->facc[0] = 0;
950 body[i]->facc[1] = 0;
951 body[i]->facc[2] = 0;
952 body[i]->facc[3] = 0;
953 body[i]->tacc[0] = 0;
954 body[i]->tacc[1] = 0;
955 body[i]->tacc[2] = 0;
956 body[i]->tacc[3] = 0;
957 }
958
959#ifdef TIMING
960 dTimerEnd();
961 if (m > 0) dTimerReport (stdout,1);
962#endif
963
964 UNALLOCA(joint);
965 UNALLOCA(I);
966 UNALLOCA(invI);
967 UNALLOCA(info);
968 UNALLOCA(ofs);
969 UNALLOCA(invM);
970 UNALLOCA(fe);
971 UNALLOCA(v);
972 UNALLOCA(vnew);
973}
974
975//****************************************************************************
976// an optimized version of dInternalStepIsland1()
977
978void dInternalStepIsland_x2 (dxWorld *world, dxBody * const *body, int nb,
979 dxJoint * const *_joint, int nj, dReal stepsize)
980{
981 int i,j,k;
982#ifdef TIMING
983 dTimerStart("preprocessing");
984#endif
985
986 dReal stepsize1 = dRecip(stepsize);
987
988 // number all bodies in the body list - set their tag values
989 for (i=0; i<nb; i++) body[i]->tag = i;
990
991 // make a local copy of the joint array, because we might want to modify it.
992 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
993 // but not the joint array, because the caller might need it unchanged).
994 ALLOCA(dxJoint*,joint,nj*sizeof(dxJoint*));
995#ifdef dUSE_MALLOC_FOR_ALLOCA
996 if (joint == NULL) {
997 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
998 return;
999 }
1000#endif
1001 memcpy (joint,_joint,nj * sizeof(dxJoint*));
1002
1003 // for all bodies, compute the inertia tensor and its inverse in the global
1004 // frame, and compute the rotational force and add it to the torque
1005 // accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
1006 // @@@ check computation of rotational force.
1007#ifdef dGYROSCOPIC
1008 ALLOCA(dReal,I,3*nb*4*sizeof(dReal));
1009# ifdef dUSE_MALLOC_FOR_ALLOCA
1010 if (I == NULL) {
1011 UNALLOCA(joint);
1012 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1013 return;
1014 }
1015# endif
1016#else
1017 dReal *I = NULL;
1018#endif // for dGYROSCOPIC
1019
1020 ALLOCA(dReal,invI,3*nb*4*sizeof(dReal));
1021#ifdef dUSE_MALLOC_FOR_ALLOCA
1022 if (invI == NULL) {
1023 UNALLOCA(I);
1024 UNALLOCA(joint);
1025 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1026 return;
1027 }
1028#endif
1029
1030 //dSetZero (I,3*nb*4);
1031 //dSetZero (invI,3*nb*4);
1032 for (i=0; i<nb; i++) {
1033 dReal tmp[12];
1034
1035 // compute inverse inertia tensor in global frame
1036 dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
1037 dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
1038#ifdef dGYROSCOPIC
1039 // compute inertia tensor in global frame
1040 dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
1041 dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
1042
1043 // compute rotational force
1044 dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
1045 dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
1046#endif
1047 }
1048
1049 // add the gravity force to all bodies
1050 for (i=0; i<nb; i++) {
1051 if ((body[i]->flags & dxBodyNoGravity)==0) {
1052 body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
1053 body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
1054 body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
1055 }
1056 }
1057
1058 // get m = total constraint dimension, nub = number of unbounded variables.
1059 // create constraint offset array and number-of-rows array for all joints.
1060 // the constraints are re-ordered as follows: the purely unbounded
1061 // constraints, the mixed unbounded + LCP constraints, and last the purely
1062 // LCP constraints. this assists the LCP solver to put all unbounded
1063 // variables at the start for a quick factorization.
1064 //
1065 // joints with m=0 are inactive and are removed from the joints array
1066 // entirely, so that the code that follows does not consider them.
1067 // also number all active joints in the joint list (set their tag values).
1068 // inactive joints receive a tag value of -1.
1069
1070 int m = 0;
1071 ALLOCA(dxJoint::Info1,info,nj*sizeof(dxJoint::Info1));
1072#ifdef dUSE_MALLOC_FOR_ALLOCA
1073 if (info == NULL) {
1074 UNALLOCA(invI);
1075 UNALLOCA(I);
1076 UNALLOCA(joint);
1077 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1078 return;
1079 }
1080#endif
1081 ALLOCA(int,ofs,nj*sizeof(int));
1082#ifdef dUSE_MALLOC_FOR_ALLOCA
1083 if (ofs == NULL) {
1084 UNALLOCA(info);
1085 UNALLOCA(invI);
1086 UNALLOCA(I);
1087 UNALLOCA(joint);
1088 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1089 return;
1090 }
1091#endif
1092 for (i=0, j=0; j<nj; j++) { // i=dest, j=src
1093 joint[j]->vtable->getInfo1 (joint[j],info+i);
1094 dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
1095 info[i].nub >= 0 && info[i].nub <= info[i].m);
1096 if (info[i].m > 0) {
1097 joint[i] = joint[j];
1098 joint[i]->tag = i;
1099 i++;
1100 }
1101 else {
1102 joint[j]->tag = -1;
1103 }
1104 }
1105 nj = i;
1106
1107 // the purely unbounded constraints
1108 for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
1109 ofs[i] = m;
1110 m += info[i].m;
1111 }
1112 int nub = m;
1113 // the mixed unbounded + LCP constraints
1114 for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
1115 ofs[i] = m;
1116 m += info[i].m;
1117 }
1118 // the purely LCP constraints
1119 for (i=0; i<nj; i++) if (info[i].nub == 0) {
1120 ofs[i] = m;
1121 m += info[i].m;
1122 }
1123
1124 // this will be set to the force due to the constraints
1125 ALLOCA(dReal,cforce,nb*8*sizeof(dReal));
1126#ifdef dUSE_MALLOC_FOR_ALLOCA
1127 if (cforce == NULL) {
1128 UNALLOCA(ofs);
1129 UNALLOCA(info);
1130 UNALLOCA(invI);
1131 UNALLOCA(I);
1132 UNALLOCA(joint);
1133 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1134 return;
1135 }
1136#endif
1137 dSetZero (cforce,nb*8);
1138
1139 // if there are constraints, compute cforce
1140 if (m > 0) {
1141 // create a constraint equation right hand side vector `c', a constraint
1142 // force mixing vector `cfm', and LCP low and high bound vectors, and an
1143 // 'findex' vector.
1144 ALLOCA(dReal,c,m*sizeof(dReal));
1145#ifdef dUSE_MALLOC_FOR_ALLOCA
1146 if (c == NULL) {
1147 UNALLOCA(cforce);
1148 UNALLOCA(ofs);
1149 UNALLOCA(info);
1150 UNALLOCA(invI);
1151 UNALLOCA(I);
1152 UNALLOCA(joint);
1153 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1154 return;
1155 }
1156#endif
1157 ALLOCA(dReal,cfm,m*sizeof(dReal));
1158#ifdef dUSE_MALLOC_FOR_ALLOCA
1159 if (cfm == NULL) {
1160 UNALLOCA(c);
1161 UNALLOCA(cforce);
1162 UNALLOCA(ofs);
1163 UNALLOCA(info);
1164 UNALLOCA(invI);
1165 UNALLOCA(I);
1166 UNALLOCA(joint);
1167 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1168 return;
1169 }
1170#endif
1171 ALLOCA(dReal,lo,m*sizeof(dReal));
1172#ifdef dUSE_MALLOC_FOR_ALLOCA
1173 if (lo == NULL) {
1174 UNALLOCA(cfm);
1175 UNALLOCA(c);
1176 UNALLOCA(cforce);
1177 UNALLOCA(ofs);
1178 UNALLOCA(info);
1179 UNALLOCA(invI);
1180 UNALLOCA(I);
1181 UNALLOCA(joint);
1182 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1183 return;
1184 }
1185#endif
1186 ALLOCA(dReal,hi,m*sizeof(dReal));
1187#ifdef dUSE_MALLOC_FOR_ALLOCA
1188 if (hi == NULL) {
1189 UNALLOCA(lo);
1190 UNALLOCA(cfm);
1191 UNALLOCA(c);
1192 UNALLOCA(cforce);
1193 UNALLOCA(ofs);
1194 UNALLOCA(info);
1195 UNALLOCA(invI);
1196 UNALLOCA(I);
1197 UNALLOCA(joint);
1198 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1199 return;
1200 }
1201#endif
1202 ALLOCA(int,findex,m*sizeof(int));
1203#ifdef dUSE_MALLOC_FOR_ALLOCA
1204 if (findex == NULL) {
1205 UNALLOCA(hi);
1206 UNALLOCA(lo);
1207 UNALLOCA(cfm);
1208 UNALLOCA(c);
1209 UNALLOCA(cforce);
1210 UNALLOCA(ofs);
1211 UNALLOCA(info);
1212 UNALLOCA(invI);
1213 UNALLOCA(I);
1214 UNALLOCA(joint);
1215 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1216 return;
1217 }
1218#endif
1219 dSetZero (c,m);
1220 dSetValue (cfm,m,world->global_cfm);
1221 dSetValue (lo,m,-dInfinity);
1222 dSetValue (hi,m, dInfinity);
1223 for (i=0; i<m; i++) findex[i] = -1;
1224
1225 // get jacobian data from constraints. a (2*m)x8 matrix will be created
1226 // to store the two jacobian blocks from each constraint. it has this
1227 // format:
1228 //
1229 // l l l 0 a a a 0 \ .
1230 // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows)
1231 // l l l 0 a a a 0 /
1232 // l l l 0 a a a 0 \ .
1233 // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows)
1234 // l l l 0 a a a 0 /
1235 // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row)
1236 // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row)
1237 // etc...
1238 //
1239 // (lll) = linear jacobian data
1240 // (aaa) = angular jacobian data
1241 //
1242# ifdef TIMING
1243 dTimerNow ("create J");
1244# endif
1245 ALLOCA(dReal,J,2*m*8*sizeof(dReal));
1246#ifdef dUSE_MALLOC_FOR_ALLOCA
1247 if (J == NULL) {
1248 UNALLOCA(findex);
1249 UNALLOCA(hi);
1250 UNALLOCA(lo);
1251 UNALLOCA(cfm);
1252 UNALLOCA(c);
1253 UNALLOCA(cforce);
1254 UNALLOCA(ofs);
1255 UNALLOCA(info);
1256 UNALLOCA(invI);
1257 UNALLOCA(I);
1258 UNALLOCA(joint);
1259 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1260 return;
1261 }
1262#endif
1263 dSetZero (J,2*m*8);
1264 dxJoint::Info2 Jinfo;
1265 Jinfo.rowskip = 8;
1266 Jinfo.fps = stepsize1;
1267 Jinfo.erp = world->global_erp;
1268 for (i=0; i<nj; i++) {
1269 Jinfo.J1l = J + 2*8*ofs[i];
1270 Jinfo.J1a = Jinfo.J1l + 4;
1271 Jinfo.J2l = Jinfo.J1l + 8*info[i].m;
1272 Jinfo.J2a = Jinfo.J2l + 4;
1273 Jinfo.c = c + ofs[i];
1274 Jinfo.cfm = cfm + ofs[i];
1275 Jinfo.lo = lo + ofs[i];
1276 Jinfo.hi = hi + ofs[i];
1277 Jinfo.findex = findex + ofs[i];
1278 joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
1279 // adjust returned findex values for global index numbering
1280 for (j=0; j<info[i].m; j++) {
1281 if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
1282 }
1283 }
1284
1285 // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
1286 // format as J so we just go through the constraints in J multiplying by
1287 // the appropriate scalars and matrices.
1288# ifdef TIMING
1289 dTimerNow ("compute A");
1290# endif
1291 ALLOCA(dReal,JinvM,2*m*8*sizeof(dReal));
1292#ifdef dUSE_MALLOC_FOR_ALLOCA
1293 if (JinvM == NULL) {
1294 UNALLOCA(J);
1295 UNALLOCA(findex);
1296 UNALLOCA(hi);
1297 UNALLOCA(lo);
1298 UNALLOCA(cfm);
1299 UNALLOCA(c);
1300 UNALLOCA(cforce);
1301 UNALLOCA(ofs);
1302 UNALLOCA(info);
1303 UNALLOCA(invI);
1304 UNALLOCA(I);
1305 UNALLOCA(joint);
1306 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1307 return;
1308 }
1309#endif
1310 dSetZero (JinvM,2*m*8);
1311 for (i=0; i<nj; i++) {
1312 int b = joint[i]->node[0].body->tag;
1313 dReal body_invMass = body[b]->invMass;
1314 dReal *body_invI = invI + b*12;
1315 dReal *Jsrc = J + 2*8*ofs[i];
1316 dReal *Jdst = JinvM + 2*8*ofs[i];
1317 for (j=info[i].m-1; j>=0; j--) {
1318 for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
1319 dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
1320 Jsrc += 8;
1321 Jdst += 8;
1322 }
1323 if (joint[i]->node[1].body) {
1324 b = joint[i]->node[1].body->tag;
1325 body_invMass = body[b]->invMass;
1326 body_invI = invI + b*12;
1327 for (j=info[i].m-1; j>=0; j--) {
1328 for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
1329 dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
1330 Jsrc += 8;
1331 Jdst += 8;
1332 }
1333 }
1334 }
1335
1336 // now compute A = JinvM * J'. A's rows and columns are grouped by joint,
1337 // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero
1338 // if joints i and j have at least one body in common. this fact suggests
1339 // the algorithm used to fill A:
1340 //
1341 // for b = all bodies
1342 // n = number of joints attached to body b
1343 // for i = 1..n
1344 // for j = i+1..n
1345 // ii = actual joint number for i
1346 // jj = actual joint number for j
1347 // // (ii,jj) will be set to all pairs of joints around body b
1348 // compute blockwise: A(ii,jj) += JinvM(ii) * J(jj)'
1349 //
1350 // this algorithm catches all pairs of joints that have at least one body
1351 // in common. it does not compute the diagonal blocks of A however -
1352 // another similar algorithm does that.
1353
1354 int mskip = dPAD(m);
1355 ALLOCA(dReal,A,m*mskip*sizeof(dReal));
1356#ifdef dUSE_MALLOC_FOR_ALLOCA
1357 if (A == NULL) {
1358 UNALLOCA(JinvM);
1359 UNALLOCA(J);
1360 UNALLOCA(findex);
1361 UNALLOCA(hi);
1362 UNALLOCA(lo);
1363 UNALLOCA(cfm);
1364 UNALLOCA(c);
1365 UNALLOCA(cforce);
1366 UNALLOCA(ofs);
1367 UNALLOCA(info);
1368 UNALLOCA(invI);
1369 UNALLOCA(I);
1370 UNALLOCA(joint);
1371 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1372 return;
1373 }
1374#endif
1375 dSetZero (A,m*mskip);
1376 for (i=0; i<nb; i++) {
1377 for (dxJointNode *n1=body[i]->firstjoint; n1; n1=n1->next) {
1378 for (dxJointNode *n2=n1->next; n2; n2=n2->next) {
1379 // get joint numbers and ensure ofs[j1] >= ofs[j2]
1380 int j1 = n1->joint->tag;
1381 int j2 = n2->joint->tag;
1382 if (ofs[j1] < ofs[j2]) {
1383 int tmp = j1;
1384 j1 = j2;
1385 j2 = tmp;
1386 }
1387
1388 // if either joint was tagged as -1 then it is an inactive (m=0)
1389 // joint that should not be considered
1390 if (j1==-1 || j2==-1) continue;
1391
1392 // determine if body i is the 1st or 2nd body of joints j1 and j2
1393 int jb1 = (joint[j1]->node[1].body == body[i]);
1394 int jb2 = (joint[j2]->node[1].body == body[i]);
1395 // jb1/jb2 must be 0 for joints with only one body
1396 dIASSERT(joint[j1]->node[1].body || jb1==0);
1397 dIASSERT(joint[j2]->node[1].body || jb2==0);
1398
1399 // set block of A
1400 MultiplyAdd2_p8r (A + ofs[j1]*mskip + ofs[j2],
1401 JinvM + 2*8*ofs[j1] + jb1*8*info[j1].m,
1402 J + 2*8*ofs[j2] + jb2*8*info[j2].m,
1403 info[j1].m,info[j2].m, mskip);
1404 }
1405 }
1406 }
1407 // compute diagonal blocks of A
1408 for (i=0; i<nj; i++) {
1409 Multiply2_p8r (A + ofs[i]*(mskip+1),
1410 JinvM + 2*8*ofs[i],
1411 J + 2*8*ofs[i],
1412 info[i].m,info[i].m, mskip);
1413 if (joint[i]->node[1].body) {
1414 MultiplyAdd2_p8r (A + ofs[i]*(mskip+1),
1415 JinvM + 2*8*ofs[i] + 8*info[i].m,
1416 J + 2*8*ofs[i] + 8*info[i].m,
1417 info[i].m,info[i].m, mskip);
1418 }
1419 }
1420
1421 // add cfm to the diagonal of A
1422 for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * stepsize1;
1423
1424# ifdef COMPARE_METHODS
1425 comparator.nextMatrix (A,m,m,1,"A");
1426# endif
1427
1428 // compute the right hand side `rhs'
1429# ifdef TIMING
1430 dTimerNow ("compute rhs");
1431# endif
1432 ALLOCA(dReal,tmp1,nb*8*sizeof(dReal));
1433#ifdef dUSE_MALLOC_FOR_ALLOCA
1434 if (tmp1 == NULL) {
1435 UNALLOCA(A);
1436 UNALLOCA(JinvM);
1437 UNALLOCA(J);
1438 UNALLOCA(findex);
1439 UNALLOCA(hi);
1440 UNALLOCA(lo);
1441 UNALLOCA(cfm);
1442 UNALLOCA(c);
1443 UNALLOCA(cforce);
1444 UNALLOCA(ofs);
1445 UNALLOCA(info);
1446 UNALLOCA(invI);
1447 UNALLOCA(I);
1448 UNALLOCA(joint);
1449 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1450 return;
1451 }
1452#endif
1453 //dSetZero (tmp1,nb*8);
1454 // put v/h + invM*fe into tmp1
1455 for (i=0; i<nb; i++) {
1456 dReal body_invMass = body[i]->invMass;
1457 dReal *body_invI = invI + i*12;
1458 for (j=0; j<3; j++) tmp1[i*8+j] = body[i]->facc[j] * body_invMass +
1459 body[i]->lvel[j] * stepsize1;
1460 dMULTIPLY0_331 (tmp1 + i*8 + 4,body_invI,body[i]->tacc);
1461 for (j=0; j<3; j++) tmp1[i*8+4+j] += body[i]->avel[j] * stepsize1;
1462 }
1463 // put J*tmp1 into rhs
1464 ALLOCA(dReal,rhs,m*sizeof(dReal));
1465#ifdef dUSE_MALLOC_FOR_ALLOCA
1466 if (rhs == NULL) {
1467 UNALLOCA(tmp1);
1468 UNALLOCA(A);
1469 UNALLOCA(JinvM);
1470 UNALLOCA(J);
1471 UNALLOCA(findex);
1472 UNALLOCA(hi);
1473 UNALLOCA(lo);
1474 UNALLOCA(cfm);
1475 UNALLOCA(c);
1476 UNALLOCA(cforce);
1477 UNALLOCA(ofs);
1478 UNALLOCA(info);
1479 UNALLOCA(invI);
1480 UNALLOCA(I);
1481 UNALLOCA(joint);
1482 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1483 return;
1484 }
1485#endif
1486 //dSetZero (rhs,m);
1487 for (i=0; i<nj; i++) {
1488 dReal *JJ = J + 2*8*ofs[i];
1489 Multiply0_p81 (rhs+ofs[i],JJ,
1490 tmp1 + 8*joint[i]->node[0].body->tag, info[i].m);
1491 if (joint[i]->node[1].body) {
1492 MultiplyAdd0_p81 (rhs+ofs[i],JJ + 8*info[i].m,
1493 tmp1 + 8*joint[i]->node[1].body->tag, info[i].m);
1494 }
1495 }
1496 // complete rhs
1497 for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
1498
1499# ifdef COMPARE_METHODS
1500 comparator.nextMatrix (c,m,1,0,"c");
1501 comparator.nextMatrix (rhs,m,1,0,"rhs");
1502# endif
1503
1504 // solve the LCP problem and get lambda.
1505 // this will destroy A but that's okay
1506# ifdef TIMING
1507 dTimerNow ("solving LCP problem");
1508# endif
1509 ALLOCA(dReal,lambda,m*sizeof(dReal));
1510#ifdef dUSE_MALLOC_FOR_ALLOCA
1511 if (lambda == NULL) {
1512 UNALLOCA(rhs);
1513 UNALLOCA(tmp1);
1514 UNALLOCA(A);
1515 UNALLOCA(JinvM);
1516 UNALLOCA(J);
1517 UNALLOCA(findex);
1518 UNALLOCA(hi);
1519 UNALLOCA(lo);
1520 UNALLOCA(cfm);
1521 UNALLOCA(c);
1522 UNALLOCA(cforce);
1523 UNALLOCA(ofs);
1524 UNALLOCA(info);
1525 UNALLOCA(invI);
1526 UNALLOCA(I);
1527 UNALLOCA(joint);
1528 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1529 return;
1530 }
1531#endif
1532 ALLOCA(dReal,residual,m*sizeof(dReal));
1533#ifdef dUSE_MALLOC_FOR_ALLOCA
1534 if (residual == NULL) {
1535 UNALLOCA(lambda);
1536 UNALLOCA(rhs);
1537 UNALLOCA(tmp1);
1538 UNALLOCA(A);
1539 UNALLOCA(JinvM);
1540 UNALLOCA(J);
1541 UNALLOCA(findex);
1542 UNALLOCA(hi);
1543 UNALLOCA(lo);
1544 UNALLOCA(cfm);
1545 UNALLOCA(c);
1546 UNALLOCA(cforce);
1547 UNALLOCA(ofs);
1548 UNALLOCA(info);
1549 UNALLOCA(invI);
1550 UNALLOCA(I);
1551 UNALLOCA(joint);
1552 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1553 return;
1554 }
1555#endif
1556 dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
1557
1558#ifdef dUSE_MALLOC_FOR_ALLOCA
1559 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
1560 return;
1561#endif
1562
1563
1564// OLD WAY - direct factor and solve
1565//
1566// // factorize A (L*L'=A)
1567//# ifdef TIMING
1568// dTimerNow ("factorize A");
1569//# endif
1570// dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
1571// memcpy (L,A,m*mskip*sizeof(dReal));
1572//# ifdef FAST_FACTOR
1573// dFastFactorCholesky (L,m); // does not report non positive definiteness
1574//# else
1575// if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
1576//# endif
1577//
1578// // compute lambda
1579//# ifdef TIMING
1580// dTimerNow ("compute lambda");
1581//# endif
1582// dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
1583// memcpy (lambda,rhs,m * sizeof(dReal));
1584// dSolveCholesky (L,lambda,m);
1585
1586# ifdef COMPARE_METHODS
1587 comparator.nextMatrix (lambda,m,1,0,"lambda");
1588# endif
1589
1590 // compute the constraint force `cforce'
1591# ifdef TIMING
1592 dTimerNow ("compute constraint force");
1593# endif
1594 // compute cforce = J'*lambda
1595 for (i=0; i<nj; i++) {
1596 dReal *JJ = J + 2*8*ofs[i];
1597 dxBody* b1 = joint[i]->node[0].body;
1598 dxBody* b2 = joint[i]->node[1].body;
1599 dJointFeedback *fb = joint[i]->feedback;
1600
1601 if (fb) {
1602 // the user has requested feedback on the amount of force that this
1603 // joint is applying to the bodies. we use a slightly slower
1604 // computation that splits out the force components and puts them
1605 // in the feedback structure.
1606 dReal data1[8],data2[8];
1607 Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m);
1608 dReal *cf1 = cforce + 8*b1->tag;
1609 cf1[0] += (fb->f1[0] = data1[0]);
1610 cf1[1] += (fb->f1[1] = data1[1]);
1611 cf1[2] += (fb->f1[2] = data1[2]);
1612 cf1[4] += (fb->t1[0] = data1[4]);
1613 cf1[5] += (fb->t1[1] = data1[5]);
1614 cf1[6] += (fb->t1[2] = data1[6]);
1615 if (b2){
1616 Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
1617 dReal *cf2 = cforce + 8*b2->tag;
1618 cf2[0] += (fb->f2[0] = data2[0]);
1619 cf2[1] += (fb->f2[1] = data2[1]);
1620 cf2[2] += (fb->f2[2] = data2[2]);
1621 cf2[4] += (fb->t2[0] = data2[4]);
1622 cf2[5] += (fb->t2[1] = data2[5]);
1623 cf2[6] += (fb->t2[2] = data2[6]);
1624 }
1625 }
1626 else {
1627 // no feedback is required, let's compute cforce the faster way
1628 MultiplyAdd1_8q1 (cforce + 8*b1->tag,JJ, lambda+ofs[i], info[i].m);
1629 if (b2) {
1630 MultiplyAdd1_8q1 (cforce + 8*b2->tag,
1631 JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
1632 }
1633 }
1634 }
1635 UNALLOCA(c);
1636 UNALLOCA(cfm);
1637 UNALLOCA(lo);
1638 UNALLOCA(hi);
1639 UNALLOCA(findex);
1640 UNALLOCA(J);
1641 UNALLOCA(JinvM);
1642 UNALLOCA(A);
1643 UNALLOCA(tmp1);
1644 UNALLOCA(rhs);
1645 UNALLOCA(lambda);
1646 UNALLOCA(residual);
1647 }
1648
1649 // compute the velocity update
1650#ifdef TIMING
1651 dTimerNow ("compute velocity update");
1652#endif
1653
1654 // add fe to cforce
1655 for (i=0; i<nb; i++) {
1656 for (j=0; j<3; j++) cforce[i*8+j] += body[i]->facc[j];
1657 for (j=0; j<3; j++) cforce[i*8+4+j] += body[i]->tacc[j];
1658 }
1659 // multiply cforce by stepsize
1660 for (i=0; i < nb*8; i++) cforce[i] *= stepsize;
1661 // add invM * cforce to the body velocity
1662 for (i=0; i<nb; i++) {
1663 dReal body_invMass = body[i]->invMass;
1664 dReal *body_invI = invI + i*12;
1665 for (j=0; j<3; j++) body[i]->lvel[j] += body_invMass * cforce[i*8+j];
1666 dMULTIPLYADD0_331 (body[i]->avel,body_invI,cforce+i*8+4);
1667 }
1668
1669 // update the position and orientation from the new linear/angular velocity
1670 // (over the given timestep)
1671# ifdef TIMING
1672 dTimerNow ("update position");
1673# endif
1674 for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
1675
1676#ifdef COMPARE_METHODS
1677 ALLOCA(dReal,tmp, ALLOCA (nb*6*sizeof(dReal));
1678#ifdef dUSE_MALLOC_FOR_ALLOCA
1679 if (tmp == NULL) {
1680 UNALLOCA(cforce);
1681 UNALLOCA(ofs);
1682 UNALLOCA(info);
1683 UNALLOCA(invI);
1684 UNALLOCA(I);
1685 UNALLOCA(joint);
1686 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1687 return;
1688 }
1689#endif
1690 for (i=0; i<nb; i++) {
1691 for (j=0; j<3; j++) tmp_vnew[i*6+j] = body[i]->lvel[j];
1692 for (j=0; j<3; j++) tmp_vnew[i*6+3+j] = body[i]->avel[j];
1693 }
1694 comparator.nextMatrix (tmp_vnew,nb*6,1,0,"vnew");
1695 UNALLOCA(tmp);
1696#endif
1697
1698#ifdef TIMING
1699 dTimerNow ("tidy up");
1700#endif
1701
1702 // zero all force accumulators
1703 for (i=0; i<nb; i++) {
1704 body[i]->facc[0] = 0;
1705 body[i]->facc[1] = 0;
1706 body[i]->facc[2] = 0;
1707 body[i]->facc[3] = 0;
1708 body[i]->tacc[0] = 0;
1709 body[i]->tacc[1] = 0;
1710 body[i]->tacc[2] = 0;
1711 body[i]->tacc[3] = 0;
1712 }
1713
1714#ifdef TIMING
1715 dTimerEnd();
1716 if (m > 0) dTimerReport (stdout,1);
1717#endif
1718
1719 UNALLOCA(joint);
1720 UNALLOCA(I);
1721 UNALLOCA(invI);
1722 UNALLOCA(info);
1723 UNALLOCA(ofs);
1724 UNALLOCA(cforce);
1725}
1726
1727//****************************************************************************
1728
1729void dInternalStepIsland (dxWorld *world, dxBody * const *body, int nb,
1730 dxJoint * const *joint, int nj, dReal stepsize)
1731{
1732
1733#ifdef dUSE_MALLOC_FOR_ALLOCA
1734 dMemoryFlag = d_MEMORY_OK;
1735#endif
1736
1737#ifndef COMPARE_METHODS
1738 dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
1739
1740#ifdef dUSE_MALLOC_FOR_ALLOCA
1741 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1742 REPORT_OUT_OF_MEMORY;
1743 return;
1744 }
1745#endif
1746
1747#endif
1748
1749#ifdef COMPARE_METHODS
1750 int i;
1751
1752 // save body state
1753 ALLOCA(dxBody,state,nb*sizeof(dxBody));
1754#ifdef dUSE_MALLOC_FOR_ALLOCA
1755 if (state == NULL) {
1756 dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
1757 REPORT_OUT_OF_MEMORY;
1758 return;
1759 }
1760#endif
1761 for (i=0; i<nb; i++) memcpy (state+i,body[i],sizeof(dxBody));
1762
1763 // take slow step
1764 comparator.reset();
1765 dInternalStepIsland_x1 (world,body,nb,joint,nj,stepsize);
1766 comparator.end();
1767#ifdef dUSE_MALLOC_FOR_ALLOCA
1768 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1769 UNALLOCA(state);
1770 REPORT_OUT_OF_MEMORY;
1771 return;
1772 }
1773#endif
1774
1775 // restore state
1776 for (i=0; i<nb; i++) memcpy (body[i],state+i,sizeof(dxBody));
1777
1778 // take fast step
1779 dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
1780 comparator.end();
1781#ifdef dUSE_MALLOC_FOR_ALLOCA
1782 if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
1783 UNALLOCA(state);
1784 REPORT_OUT_OF_MEMORY;
1785 return;
1786 }
1787#endif
1788
1789 //comparator.dump();
1790 //_exit (1);
1791 UNALLOCA(state);
1792#endif
1793}
1794
1795
diff --git a/libraries/ode-0.9/ode/src/step.h b/libraries/ode-0.9/ode/src/step.h
deleted file mode 100644
index 4947253..0000000
--- a/libraries/ode-0.9/ode/src/step.h
+++ /dev/null
@@ -1,36 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifndef _ODE_STEP_H_
24#define _ODE_STEP_H_
25
26#include <ode/common.h>
27
28
29void dInternalStepIsland (dxWorld *world,
30 dxBody * const *body, int nb,
31 dxJoint * const *joint, int nj,
32 dReal stepsize);
33
34
35
36#endif
diff --git a/libraries/ode-0.9/ode/src/stepfast.cpp b/libraries/ode-0.9/ode/src/stepfast.cpp
deleted file mode 100755
index 35c45db..0000000
--- a/libraries/ode-0.9/ode/src/stepfast.cpp
+++ /dev/null
@@ -1,1139 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * Fast iterative solver, David Whittaker. Email: david@csworkbench.com *
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of EITHER: *
10 * (1) The GNU Lesser General Public License as published by the Free *
11 * Software Foundation; either version 2.1 of the License, or (at *
12 * your option) any later version. The text of the GNU Lesser *
13 * General Public License is included with this library in the *
14 * file LICENSE.TXT. *
15 * (2) The BSD-style license that is included with this library in *
16 * the file LICENSE-BSD.TXT. *
17 * *
18 * This library is distributed in the hope that it will be useful, *
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
21 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
22 * *
23 *************************************************************************/
24
25// This is the StepFast code by David Whittaker. This code is faster, but
26// sometimes less stable than, the original "big matrix" code.
27// Refer to the user's manual for more information.
28// Note that this source file duplicates a lot of stuff from step.cpp,
29// eventually we should move the common code to a third file.
30
31#include "objects.h"
32#include "joint.h"
33#include <ode/config.h>
34#include <ode/objects.h>
35#include <ode/odemath.h>
36#include <ode/rotation.h>
37#include <ode/timer.h>
38#include <ode/error.h>
39#include <ode/matrix.h>
40#include <ode/misc.h>
41#include "lcp.h"
42#include "step.h"
43#include "util.h"
44
45
46// misc defines
47
48#define ALLOCA dALLOCA16
49
50#define RANDOM_JOINT_ORDER
51//#define FAST_FACTOR //use a factorization approximation to the LCP solver (fast, theoretically less accurate)
52#define SLOW_LCP //use the old LCP solver
53//#define NO_ISLANDS //does not perform island creation code (3~4% of simulation time), body disabling doesn't work
54//#define TIMING
55
56
57static int autoEnableDepth = 2;
58
59void dWorldSetAutoEnableDepthSF1 (dxWorld *world, int autodepth)
60{
61 if (autodepth > 0)
62 autoEnableDepth = autodepth;
63 else
64 autoEnableDepth = 0;
65}
66
67int dWorldGetAutoEnableDepthSF1 (dxWorld *world)
68{
69 return autoEnableDepth;
70}
71
72//little bit of math.... the _sym_ functions assume the return matrix will be symmetric
73static void
74Multiply2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
75{
76 int i, j;
77 dReal sum, *aa, *ad, *bb, *cc;
78 dIASSERT (p > 0 && A && B && C);
79 bb = B;
80 for (i = 0; i < p; i++)
81 {
82 //aa is going accross the matrix, ad down
83 aa = ad = A;
84 cc = C;
85 for (j = i; j < p; j++)
86 {
87 sum = bb[0] * cc[0];
88 sum += bb[1] * cc[1];
89 sum += bb[2] * cc[2];
90 sum += bb[4] * cc[4];
91 sum += bb[5] * cc[5];
92 sum += bb[6] * cc[6];
93 *(aa++) = *ad = sum;
94 ad += Askip;
95 cc += 8;
96 }
97 bb += 8;
98 A += Askip + 1;
99 C += 8;
100 }
101}
102
103static void
104MultiplyAdd2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
105{
106 int i, j;
107 dReal sum, *aa, *ad, *bb, *cc;
108 dIASSERT (p > 0 && A && B && C);
109 bb = B;
110 for (i = 0; i < p; i++)
111 {
112 //aa is going accross the matrix, ad down
113 aa = ad = A;
114 cc = C;
115 for (j = i; j < p; j++)
116 {
117 sum = bb[0] * cc[0];
118 sum += bb[1] * cc[1];
119 sum += bb[2] * cc[2];
120 sum += bb[4] * cc[4];
121 sum += bb[5] * cc[5];
122 sum += bb[6] * cc[6];
123 *(aa++) += sum;
124 *ad += sum;
125 ad += Askip;
126 cc += 8;
127 }
128 bb += 8;
129 A += Askip + 1;
130 C += 8;
131 }
132}
133
134
135// this assumes the 4th and 8th rows of B are zero.
136
137static void
138Multiply0_p81 (dReal * A, dReal * B, dReal * C, int p)
139{
140 int i;
141 dIASSERT (p > 0 && A && B && C);
142 dReal sum;
143 for (i = p; i; i--)
144 {
145 sum = B[0] * C[0];
146 sum += B[1] * C[1];
147 sum += B[2] * C[2];
148 sum += B[4] * C[4];
149 sum += B[5] * C[5];
150 sum += B[6] * C[6];
151 *(A++) = sum;
152 B += 8;
153 }
154}
155
156
157// this assumes the 4th and 8th rows of B are zero.
158
159static void
160MultiplyAdd0_p81 (dReal * A, dReal * B, dReal * C, int p)
161{
162 int i;
163 dIASSERT (p > 0 && A && B && C);
164 dReal sum;
165 for (i = p; i; i--)
166 {
167 sum = B[0] * C[0];
168 sum += B[1] * C[1];
169 sum += B[2] * C[2];
170 sum += B[4] * C[4];
171 sum += B[5] * C[5];
172 sum += B[6] * C[6];
173 *(A++) += sum;
174 B += 8;
175 }
176}
177
178
179// this assumes the 4th and 8th rows of B are zero.
180
181static void
182Multiply1_8q1 (dReal * A, dReal * B, dReal * C, int q)
183{
184 int k;
185 dReal sum;
186 dIASSERT (q > 0 && A && B && C);
187 sum = 0;
188 for (k = 0; k < q; k++)
189 sum += B[k * 8] * C[k];
190 A[0] = sum;
191 sum = 0;
192 for (k = 0; k < q; k++)
193 sum += B[1 + k * 8] * C[k];
194 A[1] = sum;
195 sum = 0;
196 for (k = 0; k < q; k++)
197 sum += B[2 + k * 8] * C[k];
198 A[2] = sum;
199 sum = 0;
200 for (k = 0; k < q; k++)
201 sum += B[4 + k * 8] * C[k];
202 A[4] = sum;
203 sum = 0;
204 for (k = 0; k < q; k++)
205 sum += B[5 + k * 8] * C[k];
206 A[5] = sum;
207 sum = 0;
208 for (k = 0; k < q; k++)
209 sum += B[6 + k * 8] * C[k];
210 A[6] = sum;
211}
212
213//****************************************************************************
214// body rotation
215
216// return sin(x)/x. this has a singularity at 0 so special handling is needed
217// for small arguments.
218
219static inline dReal
220sinc (dReal x)
221{
222 // if |x| < 1e-4 then use a taylor series expansion. this two term expansion
223 // is actually accurate to one LS bit within this range if double precision
224 // is being used - so don't worry!
225 if (dFabs (x) < 1.0e-4)
226 return REAL (1.0) - x * x * REAL (0.166666666666666666667);
227 else
228 return dSin (x) / x;
229}
230
231
232// given a body b, apply its linear and angular rotation over the time
233// interval h, thereby adjusting its position and orientation.
234
235static inline void
236moveAndRotateBody (dxBody * b, dReal h)
237{
238 int j;
239
240 // handle linear velocity
241 for (j = 0; j < 3; j++)
242 b->posr.pos[j] += h * b->lvel[j];
243
244 if (b->flags & dxBodyFlagFiniteRotation)
245 {
246 dVector3 irv; // infitesimal rotation vector
247 dQuaternion q; // quaternion for finite rotation
248
249 if (b->flags & dxBodyFlagFiniteRotationAxis)
250 {
251 // split the angular velocity vector into a component along the finite
252 // rotation axis, and a component orthogonal to it.
253 dVector3 frv, irv; // finite rotation vector
254 dReal k = dDOT (b->finite_rot_axis, b->avel);
255 frv[0] = b->finite_rot_axis[0] * k;
256 frv[1] = b->finite_rot_axis[1] * k;
257 frv[2] = b->finite_rot_axis[2] * k;
258 irv[0] = b->avel[0] - frv[0];
259 irv[1] = b->avel[1] - frv[1];
260 irv[2] = b->avel[2] - frv[2];
261
262 // make a rotation quaternion q that corresponds to frv * h.
263 // compare this with the full-finite-rotation case below.
264 h *= REAL (0.5);
265 dReal theta = k * h;
266 q[0] = dCos (theta);
267 dReal s = sinc (theta) * h;
268 q[1] = frv[0] * s;
269 q[2] = frv[1] * s;
270 q[3] = frv[2] * s;
271 }
272 else
273 {
274 // make a rotation quaternion q that corresponds to w * h
275 dReal wlen = dSqrt (b->avel[0] * b->avel[0] + b->avel[1] * b->avel[1] + b->avel[2] * b->avel[2]);
276 h *= REAL (0.5);
277 dReal theta = wlen * h;
278 q[0] = dCos (theta);
279 dReal s = sinc (theta) * h;
280 q[1] = b->avel[0] * s;
281 q[2] = b->avel[1] * s;
282 q[3] = b->avel[2] * s;
283 }
284
285 // do the finite rotation
286 dQuaternion q2;
287 dQMultiply0 (q2, q, b->q);
288 for (j = 0; j < 4; j++)
289 b->q[j] = q2[j];
290
291 // do the infitesimal rotation if required
292 if (b->flags & dxBodyFlagFiniteRotationAxis)
293 {
294 dReal dq[4];
295 dWtoDQ (irv, b->q, dq);
296 for (j = 0; j < 4; j++)
297 b->q[j] += h * dq[j];
298 }
299 }
300 else
301 {
302 // the normal way - do an infitesimal rotation
303 dReal dq[4];
304 dWtoDQ (b->avel, b->q, dq);
305 for (j = 0; j < 4; j++)
306 b->q[j] += h * dq[j];
307 }
308
309 // normalize the quaternion and convert it to a rotation matrix
310 dNormalize4 (b->q);
311 dQtoR (b->q, b->posr.R);
312
313 // notify all attached geoms that this body has moved
314 for (dxGeom * geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
315 dGeomMoved (geom);
316}
317
318//****************************************************************************
319//This is an implementation of the iterated/relaxation algorithm.
320//Here is a quick overview of the algorithm per Sergi Valverde's posts to the
321//mailing list:
322//
323// for i=0..N-1 do
324// for c = 0..C-1 do
325// Solve constraint c-th
326// Apply forces to constraint bodies
327// next
328// next
329// Integrate bodies
330
331void
332dInternalStepFast (dxWorld * world, dxBody * body[2], dReal * GI[2], dReal * GinvI[2], dxJoint * joint, dxJoint::Info1 info, dxJoint::Info2 Jinfo, dReal stepsize)
333{
334 int i, j, k;
335# ifdef TIMING
336 dTimerNow ("constraint preprocessing");
337# endif
338
339 dReal stepsize1 = dRecip (stepsize);
340
341 int m = info.m;
342 // nothing to do if no constraints.
343 if (m <= 0)
344 return;
345
346 int nub = 0;
347 if (info.nub == info.m)
348 nub = m;
349
350 // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
351 // format as J so we just go through the constraints in J multiplying by
352 // the appropriate scalars and matrices.
353# ifdef TIMING
354 dTimerNow ("compute A");
355# endif
356 dReal JinvM[2 * 6 * 8];
357 //dSetZero (JinvM, 2 * m * 8);
358
359 dReal *Jsrc = Jinfo.J1l;
360 dReal *Jdst = JinvM;
361 if (body[0])
362 {
363 for (j = m - 1; j >= 0; j--)
364 {
365 for (k = 0; k < 3; k++)
366 Jdst[k] = Jsrc[k] * body[0]->invMass;
367 dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[0]);
368 Jsrc += 8;
369 Jdst += 8;
370 }
371 }
372 if (body[1])
373 {
374 Jsrc = Jinfo.J2l;
375 Jdst = JinvM + 8 * m;
376 for (j = m - 1; j >= 0; j--)
377 {
378 for (k = 0; k < 3; k++)
379 Jdst[k] = Jsrc[k] * body[1]->invMass;
380 dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[1]);
381 Jsrc += 8;
382 Jdst += 8;
383 }
384 }
385
386
387 // now compute A = JinvM * J'.
388 int mskip = dPAD (m);
389 dReal A[6 * 8];
390 //dSetZero (A, 6 * 8);
391
392 if (body[0]) {
393 Multiply2_sym_p8p (A, JinvM, Jinfo.J1l, m, mskip);
394 if (body[1])
395 MultiplyAdd2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l,
396 m, mskip);
397 } else {
398 if (body[1])
399 Multiply2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l,
400 m, mskip);
401 }
402
403 // add cfm to the diagonal of A
404 for (i = 0; i < m; i++)
405 A[i * mskip + i] += Jinfo.cfm[i] * stepsize1;
406
407 // compute the right hand side `rhs'
408# ifdef TIMING
409 dTimerNow ("compute rhs");
410# endif
411 dReal tmp1[16];
412 //dSetZero (tmp1, 16);
413 // put v/h + invM*fe into tmp1
414 for (i = 0; i < 2; i++)
415 {
416 if (!body[i])
417 continue;
418 for (j = 0; j < 3; j++)
419 tmp1[i * 8 + j] = body[i]->facc[j] * body[i]->invMass + body[i]->lvel[j] * stepsize1;
420 dMULTIPLY0_331 (tmp1 + i * 8 + 4, GinvI[i], body[i]->tacc);
421 for (j = 0; j < 3; j++)
422 tmp1[i * 8 + 4 + j] += body[i]->avel[j] * stepsize1;
423 }
424 // put J*tmp1 into rhs
425 dReal rhs[6];
426 //dSetZero (rhs, 6);
427
428 if (body[0]) {
429 Multiply0_p81 (rhs, Jinfo.J1l, tmp1, m);
430 if (body[1])
431 MultiplyAdd0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m);
432 } else {
433 if (body[1])
434 Multiply0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m);
435 }
436
437 // complete rhs
438 for (i = 0; i < m; i++)
439 rhs[i] = Jinfo.c[i] * stepsize1 - rhs[i];
440
441#ifdef SLOW_LCP
442 // solve the LCP problem and get lambda.
443 // this will destroy A but that's okay
444# ifdef TIMING
445 dTimerNow ("solving LCP problem");
446# endif
447 dReal *lambda = (dReal *) ALLOCA (m * sizeof (dReal));
448 dReal *residual = (dReal *) ALLOCA (m * sizeof (dReal));
449 dReal lo[6], hi[6];
450 memcpy (lo, Jinfo.lo, m * sizeof (dReal));
451 memcpy (hi, Jinfo.hi, m * sizeof (dReal));
452 dSolveLCP (m, A, lambda, rhs, residual, nub, lo, hi, Jinfo.findex);
453#endif
454
455 // LCP Solver replacement:
456 // This algorithm goes like this:
457 // Do a straightforward LDLT factorization of the matrix A, solving for
458 // A*x = rhs
459 // For each x[i] that is outside of the bounds of lo[i] and hi[i],
460 // clamp x[i] into that range.
461 // Substitute into A the now known x's
462 // subtract the residual away from the rhs.
463 // Remove row and column i from L, updating the factorization
464 // place the known x's at the end of the array, keeping up with location in p
465 // Repeat until all constraints have been clamped or all are within bounds
466 //
467 // This is probably only faster in the single joint case where only one repeat is
468 // the norm.
469
470#ifdef FAST_FACTOR
471 // factorize A (L*D*L'=A)
472# ifdef TIMING
473 dTimerNow ("factorize A");
474# endif
475 dReal d[6];
476 dReal L[6 * 8];
477 memcpy (L, A, m * mskip * sizeof (dReal));
478 dFactorLDLT (L, d, m, mskip);
479
480 // compute lambda
481# ifdef TIMING
482 dTimerNow ("compute lambda");
483# endif
484
485 int left = m; //constraints left to solve.
486 int remove[6];
487 dReal lambda[6];
488 dReal x[6];
489 int p[6];
490 for (i = 0; i < 6; i++)
491 p[i] = i;
492 while (true)
493 {
494 memcpy (x, rhs, left * sizeof (dReal));
495 dSolveLDLT (L, d, x, left, mskip);
496
497 int fixed = 0;
498 for (i = 0; i < left; i++)
499 {
500 j = p[i];
501 remove[i] = false;
502 // This isn't the exact same use of findex as dSolveLCP.... since x[findex]
503 // may change after I've already clamped x[i], but it should be close
504 if (Jinfo.findex[j] > -1)
505 {
506 dReal f = fabs (Jinfo.hi[j] * x[p[Jinfo.findex[j]]]);
507 if (x[i] > f)
508 x[i] = f;
509 else if (x[i] < -f)
510 x[i] = -f;
511 else
512 continue;
513 }
514 else
515 {
516 if (x[i] > Jinfo.hi[j])
517 x[i] = Jinfo.hi[j];
518 else if (x[i] < Jinfo.lo[j])
519 x[i] = Jinfo.lo[j];
520 else
521 continue;
522 }
523 remove[i] = true;
524 fixed++;
525 }
526 if (fixed == 0 || fixed == left) //no change or all constraints solved
527 break;
528
529 for (i = 0; i < left; i++) //sub in to right hand side.
530 if (remove[i])
531 for (j = 0; j < left; j++)
532 if (!remove[j])
533 rhs[j] -= A[j * mskip + i] * x[i];
534
535 for (int r = left - 1; r >= 0; r--) //eliminate row/col for fixed variables
536 {
537 if (remove[r])
538 {
539 //dRemoveLDLT adapted for use without row pointers.
540 if (r == left - 1)
541 {
542 left--;
543 continue; // deleting last row/col is easy
544 }
545 else if (r == 0)
546 {
547 dReal a[6];
548 for (i = 0; i < left; i++)
549 a[i] = -A[i * mskip];
550 a[0] += REAL (1.0);
551 dLDLTAddTL (L, d, a, left, mskip);
552 }
553 else
554 {
555 dReal t[6];
556 dReal a[6];
557 for (i = 0; i < r; i++)
558 t[i] = L[r * mskip + i] / d[i];
559 for (i = 0; i < left - r; i++)
560 a[i] = dDot (L + (r + i) * mskip, t, r) - A[(r + i) * mskip + r];
561 a[0] += REAL (1.0);
562 dLDLTAddTL (L + r * mskip + r, d + r, a, left - r, mskip);
563 }
564
565 dRemoveRowCol (L, left, mskip, r);
566 //end dRemoveLDLT
567
568 left--;
569 if (r < (left - 1))
570 {
571 dReal tx = x[r];
572 memmove (d + r, d + r + 1, (left - r) * sizeof (dReal));
573 memmove (rhs + r, rhs + r + 1, (left - r) * sizeof (dReal));
574 //x will get written over by rhs anyway, no need to move it around
575 //just store the fixed value we just discovered in it.
576 x[left] = tx;
577 for (i = 0; i < m; i++)
578 if (p[i] > r && p[i] <= left)
579 p[i]--;
580 p[r] = left;
581 }
582 }
583 }
584 }
585
586 for (i = 0; i < m; i++)
587 lambda[i] = x[p[i]];
588# endif
589 // compute the constraint force `cforce'
590# ifdef TIMING
591 dTimerNow ("compute constraint force");
592#endif
593
594 // compute cforce = J'*lambda
595 dJointFeedback *fb = joint->feedback;
596 dReal cforce[16];
597 //dSetZero (cforce, 16);
598
599 if (fb)
600 {
601 // the user has requested feedback on the amount of force that this
602 // joint is applying to the bodies. we use a slightly slower
603 // computation that splits out the force components and puts them
604 // in the feedback structure.
605 dReal data1[8], data2[8];
606 if (body[0])
607 {
608 Multiply1_8q1 (data1, Jinfo.J1l, lambda, m);
609 dReal *cf1 = cforce;
610 cf1[0] = (fb->f1[0] = data1[0]);
611 cf1[1] = (fb->f1[1] = data1[1]);
612 cf1[2] = (fb->f1[2] = data1[2]);
613 cf1[4] = (fb->t1[0] = data1[4]);
614 cf1[5] = (fb->t1[1] = data1[5]);
615 cf1[6] = (fb->t1[2] = data1[6]);
616 }
617 if (body[1])
618 {
619 Multiply1_8q1 (data2, Jinfo.J2l, lambda, m);
620 dReal *cf2 = cforce + 8;
621 cf2[0] = (fb->f2[0] = data2[0]);
622 cf2[1] = (fb->f2[1] = data2[1]);
623 cf2[2] = (fb->f2[2] = data2[2]);
624 cf2[4] = (fb->t2[0] = data2[4]);
625 cf2[5] = (fb->t2[1] = data2[5]);
626 cf2[6] = (fb->t2[2] = data2[6]);
627 }
628 }
629 else
630 {
631 // no feedback is required, let's compute cforce the faster way
632 if (body[0])
633 Multiply1_8q1 (cforce, Jinfo.J1l, lambda, m);
634 if (body[1])
635 Multiply1_8q1 (cforce + 8, Jinfo.J2l, lambda, m);
636 }
637
638 for (i = 0; i < 2; i++)
639 {
640 if (!body[i])
641 continue;
642 for (j = 0; j < 3; j++)
643 {
644 body[i]->facc[j] += cforce[i * 8 + j];
645 body[i]->tacc[j] += cforce[i * 8 + 4 + j];
646 }
647 }
648}
649
650void
651dInternalStepIslandFast (dxWorld * world, dxBody * const *bodies, int nb, dxJoint * const *_joints, int nj, dReal stepsize, int maxiterations)
652{
653# ifdef TIMING
654 dTimerNow ("preprocessing");
655# endif
656 dxBody *bodyPair[2], *body;
657 dReal *GIPair[2], *GinvIPair[2];
658 dxJoint *joint;
659 int iter, b, j, i;
660 dReal ministep = stepsize / maxiterations;
661
662 // make a local copy of the joint array, because we might want to modify it.
663 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
664 // but not the joint array, because the caller might need it unchanged).
665 dxJoint **joints = (dxJoint **) ALLOCA (nj * sizeof (dxJoint *));
666 memcpy (joints, _joints, nj * sizeof (dxJoint *));
667
668 // get m = total constraint dimension, nub = number of unbounded variables.
669 // create constraint offset array and number-of-rows array for all joints.
670 // the constraints are re-ordered as follows: the purely unbounded
671 // constraints, the mixed unbounded + LCP constraints, and last the purely
672 // LCP constraints. this assists the LCP solver to put all unbounded
673 // variables at the start for a quick factorization.
674 //
675 // joints with m=0 are inactive and are removed from the joints array
676 // entirely, so that the code that follows does not consider them.
677 // also number all active joints in the joint list (set their tag values).
678 // inactive joints receive a tag value of -1.
679
680 int m = 0;
681 dxJoint::Info1 * info = (dxJoint::Info1 *) ALLOCA (nj * sizeof (dxJoint::Info1));
682 int *ofs = (int *) ALLOCA (nj * sizeof (int));
683 for (i = 0, j = 0; j < nj; j++)
684 { // i=dest, j=src
685 joints[j]->vtable->getInfo1 (joints[j], info + i);
686 dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
687 if (info[i].m > 0)
688 {
689 joints[i] = joints[j];
690 joints[i]->tag = i;
691 i++;
692 }
693 else
694 {
695 joints[j]->tag = -1;
696 }
697 }
698 nj = i;
699
700 // the purely unbounded constraints
701 for (i = 0; i < nj; i++)
702 {
703 ofs[i] = m;
704 m += info[i].m;
705 }
706 dReal *c = NULL;
707 dReal *cfm = NULL;
708 dReal *lo = NULL;
709 dReal *hi = NULL;
710 int *findex = NULL;
711
712 dReal *J = NULL;
713 dxJoint::Info2 * Jinfo = NULL;
714
715 if (m)
716 {
717 // create a constraint equation right hand side vector `c', a constraint
718 // force mixing vector `cfm', and LCP low and high bound vectors, and an
719 // 'findex' vector.
720 c = (dReal *) ALLOCA (m * sizeof (dReal));
721 cfm = (dReal *) ALLOCA (m * sizeof (dReal));
722 lo = (dReal *) ALLOCA (m * sizeof (dReal));
723 hi = (dReal *) ALLOCA (m * sizeof (dReal));
724 findex = (int *) ALLOCA (m * sizeof (int));
725 dSetZero (c, m);
726 dSetValue (cfm, m, world->global_cfm);
727 dSetValue (lo, m, -dInfinity);
728 dSetValue (hi, m, dInfinity);
729 for (i = 0; i < m; i++)
730 findex[i] = -1;
731
732 // get jacobian data from constraints. a (2*m)x8 matrix will be created
733 // to store the two jacobian blocks from each constraint. it has this
734 // format:
735 //
736 // l l l 0 a a a 0 \ .
737 // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows)
738 // l l l 0 a a a 0 /
739 // l l l 0 a a a 0 \ .
740 // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows)
741 // l l l 0 a a a 0 /
742 // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row)
743 // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row)
744 // etc...
745 //
746 // (lll) = linear jacobian data
747 // (aaa) = angular jacobian data
748 //
749# ifdef TIMING
750 dTimerNow ("create J");
751# endif
752 J = (dReal *) ALLOCA (2 * m * 8 * sizeof (dReal));
753 dSetZero (J, 2 * m * 8);
754 Jinfo = (dxJoint::Info2 *) ALLOCA (nj * sizeof (dxJoint::Info2));
755 for (i = 0; i < nj; i++)
756 {
757 Jinfo[i].rowskip = 8;
758 Jinfo[i].fps = dRecip (stepsize);
759 Jinfo[i].erp = world->global_erp;
760 Jinfo[i].J1l = J + 2 * 8 * ofs[i];
761 Jinfo[i].J1a = Jinfo[i].J1l + 4;
762 Jinfo[i].J2l = Jinfo[i].J1l + 8 * info[i].m;
763 Jinfo[i].J2a = Jinfo[i].J2l + 4;
764 Jinfo[i].c = c + ofs[i];
765 Jinfo[i].cfm = cfm + ofs[i];
766 Jinfo[i].lo = lo + ofs[i];
767 Jinfo[i].hi = hi + ofs[i];
768 Jinfo[i].findex = findex + ofs[i];
769 //joints[i]->vtable->getInfo2 (joints[i], Jinfo+i);
770 }
771
772 }
773
774 dReal *saveFacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
775 dReal *saveTacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
776 dReal *globalI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
777 dReal *globalInvI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
778 for (b = 0; b < nb; b++)
779 {
780 for (i = 0; i < 4; i++)
781 {
782 saveFacc[b * 4 + i] = bodies[b]->facc[i];
783 saveTacc[b * 4 + i] = bodies[b]->tacc[i];
784 }
785 bodies[b]->tag = b;
786 }
787
788 for (iter = 0; iter < maxiterations; iter++)
789 {
790# ifdef TIMING
791 dTimerNow ("applying inertia and gravity");
792# endif
793 dReal tmp[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
794
795 for (b = 0; b < nb; b++)
796 {
797 body = bodies[b];
798
799 // for all bodies, compute the inertia tensor and its inverse in the global
800 // frame, and compute the rotational force and add it to the torque
801 // accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
802 // @@@ check computation of rotational force.
803
804 // compute inertia tensor in global frame
805 dMULTIPLY2_333 (tmp, body->mass.I, body->posr.R);
806 dMULTIPLY0_333 (globalI + b * 12, body->posr.R, tmp);
807 // compute inverse inertia tensor in global frame
808 dMULTIPLY2_333 (tmp, body->invI, body->posr.R);
809 dMULTIPLY0_333 (globalInvI + b * 12, body->posr.R, tmp);
810
811 for (i = 0; i < 4; i++)
812 body->tacc[i] = saveTacc[b * 4 + i];
813#ifdef dGYROSCOPIC
814 // compute rotational force
815 dMULTIPLY0_331 (tmp, globalI + b * 12, body->avel);
816 dCROSS (body->tacc, -=, body->avel, tmp);
817#endif
818
819 // add the gravity force to all bodies
820 if ((body->flags & dxBodyNoGravity) == 0)
821 {
822 body->facc[0] = saveFacc[b * 4 + 0] + body->mass.mass * world->gravity[0];
823 body->facc[1] = saveFacc[b * 4 + 1] + body->mass.mass * world->gravity[1];
824 body->facc[2] = saveFacc[b * 4 + 2] + body->mass.mass * world->gravity[2];
825 body->facc[3] = 0;
826 } else {
827 body->facc[0] = saveFacc[b * 4 + 0];
828 body->facc[1] = saveFacc[b * 4 + 1];
829 body->facc[2] = saveFacc[b * 4 + 2];
830 body->facc[3] = 0;
831 }
832
833 }
834
835#ifdef RANDOM_JOINT_ORDER
836#ifdef TIMING
837 dTimerNow ("randomizing joint order");
838#endif
839 //randomize the order of the joints by looping through the array
840 //and swapping the current joint pointer with a random one before it.
841 for (j = 0; j < nj; j++)
842 {
843 joint = joints[j];
844 dxJoint::Info1 i1 = info[j];
845 dxJoint::Info2 i2 = Jinfo[j];
846 const int r = dRandInt(j+1);
847 dIASSERT (r < nj);
848 joints[j] = joints[r];
849 info[j] = info[r];
850 Jinfo[j] = Jinfo[r];
851 joints[r] = joint;
852 info[r] = i1;
853 Jinfo[r] = i2;
854 }
855#endif
856
857 //now iterate through the random ordered joint array we created.
858 for (j = 0; j < nj; j++)
859 {
860#ifdef TIMING
861 dTimerNow ("setting up joint");
862#endif
863 joint = joints[j];
864 bodyPair[0] = joint->node[0].body;
865 bodyPair[1] = joint->node[1].body;
866
867 if (bodyPair[0] && (bodyPair[0]->flags & dxBodyDisabled))
868 bodyPair[0] = 0;
869 if (bodyPair[1] && (bodyPair[1]->flags & dxBodyDisabled))
870 bodyPair[1] = 0;
871
872 //if this joint is not connected to any enabled bodies, skip it.
873 if (!bodyPair[0] && !bodyPair[1])
874 continue;
875
876 if (bodyPair[0])
877 {
878 GIPair[0] = globalI + bodyPair[0]->tag * 12;
879 GinvIPair[0] = globalInvI + bodyPair[0]->tag * 12;
880 }
881 if (bodyPair[1])
882 {
883 GIPair[1] = globalI + bodyPair[1]->tag * 12;
884 GinvIPair[1] = globalInvI + bodyPair[1]->tag * 12;
885 }
886
887 joints[j]->vtable->getInfo2 (joints[j], Jinfo + j);
888
889 //dInternalStepIslandFast is an exact copy of the old routine with one
890 //modification: the calculated forces are added back to the facc and tacc
891 //vectors instead of applying them to the bodies and moving them.
892 if (info[j].m > 0)
893 {
894 dInternalStepFast (world, bodyPair, GIPair, GinvIPair, joint, info[j], Jinfo[j], ministep);
895 }
896 }
897 // }
898# ifdef TIMING
899 dTimerNow ("moving bodies");
900# endif
901 //Now we can simulate all the free floating bodies, and move them.
902 for (b = 0; b < nb; b++)
903 {
904 body = bodies[b];
905
906 for (i = 0; i < 4; i++)
907 {
908 body->facc[i] *= ministep;
909 body->tacc[i] *= ministep;
910 }
911
912 //apply torque
913 dMULTIPLYADD0_331 (body->avel, globalInvI + b * 12, body->tacc);
914
915 //apply force
916 for (i = 0; i < 3; i++)
917 body->lvel[i] += body->invMass * body->facc[i];
918
919 //move It!
920 moveAndRotateBody (body, ministep);
921 }
922 }
923 for (b = 0; b < nb; b++)
924 for (j = 0; j < 4; j++)
925 bodies[b]->facc[j] = bodies[b]->tacc[j] = 0;
926}
927
928
929#ifdef NO_ISLANDS
930
931// Since the iterative algorithm doesn't care about islands of bodies, this is a
932// faster algorithm that just sends it all the joints and bodies in one array.
933// It's downfall is it's inability to handle disabled bodies as well as the old one.
934static void
935processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
936{
937 // nothing to do if no bodies
938 if (world->nb <= 0)
939 return;
940
941 dInternalHandleAutoDisabling (world,stepsize);
942
943# ifdef TIMING
944 dTimerStart ("creating joint and body arrays");
945# endif
946 dxBody **bodies, *body;
947 dxJoint **joints, *joint;
948 joints = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
949 bodies = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
950
951 int nj = 0;
952 for (joint = world->firstjoint; joint; joint = (dxJoint *) joint->next)
953 joints[nj++] = joint;
954
955 int nb = 0;
956 for (body = world->firstbody; body; body = (dxBody *) body->next)
957 bodies[nb++] = body;
958
959 dInternalStepIslandFast (world, bodies, nb, joints, nj, stepsize, maxiterations);
960# ifdef TIMING
961 dTimerEnd ();
962 dTimerReport (stdout, 1);
963# endif
964}
965
966#else
967
968//****************************************************************************
969// island processing
970
971// this groups all joints and bodies in a world into islands. all objects
972// in an island are reachable by going through connected bodies and joints.
973// each island can be simulated separately.
974// note that joints that are not attached to anything will not be included
975// in any island, an so they do not affect the simulation.
976//
977// this function starts new island from unvisited bodies. however, it will
978// never start a new islands from a disabled body. thus islands of disabled
979// bodies will not be included in the simulation. disabled bodies are
980// re-enabled if they are found to be part of an active island.
981
982static void
983processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
984{
985#ifdef TIMING
986 dTimerStart ("Island Setup");
987#endif
988 dxBody *b, *bb, **body;
989 dxJoint *j, **joint;
990
991 // nothing to do if no bodies
992 if (world->nb <= 0)
993 return;
994
995 dInternalHandleAutoDisabling (world,stepsize);
996
997 // make arrays for body and joint lists (for a single island) to go into
998 body = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
999 joint = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
1000 int bcount = 0; // number of bodies in `body'
1001 int jcount = 0; // number of joints in `joint'
1002 int tbcount = 0;
1003 int tjcount = 0;
1004
1005 // set all body/joint tags to 0
1006 for (b = world->firstbody; b; b = (dxBody *) b->next)
1007 b->tag = 0;
1008 for (j = world->firstjoint; j; j = (dxJoint *) j->next)
1009 j->tag = 0;
1010
1011 // allocate a stack of unvisited bodies in the island. the maximum size of
1012 // the stack can be the lesser of the number of bodies or joints, because
1013 // new bodies are only ever added to the stack by going through untagged
1014 // joints. all the bodies in the stack must be tagged!
1015 int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
1016 dxBody **stack = (dxBody **) ALLOCA (stackalloc * sizeof (dxBody *));
1017 int *autostack = (int *) ALLOCA (stackalloc * sizeof (int));
1018
1019 for (bb = world->firstbody; bb; bb = (dxBody *) bb->next)
1020 {
1021#ifdef TIMING
1022 dTimerNow ("Island Processing");
1023#endif
1024 // get bb = the next enabled, untagged body, and tag it
1025 if (bb->tag || (bb->flags & dxBodyDisabled))
1026 continue;
1027 bb->tag = 1;
1028
1029 // tag all bodies and joints starting from bb.
1030 int stacksize = 0;
1031 int autoDepth = autoEnableDepth;
1032 b = bb;
1033 body[0] = bb;
1034 bcount = 1;
1035 jcount = 0;
1036 goto quickstart;
1037 while (stacksize > 0)
1038 {
1039 b = stack[--stacksize]; // pop body off stack
1040 autoDepth = autostack[stacksize];
1041 body[bcount++] = b; // put body on body list
1042 quickstart:
1043
1044 // traverse and tag all body's joints, add untagged connected bodies
1045 // to stack
1046 for (dxJointNode * n = b->firstjoint; n; n = n->next)
1047 {
1048 if (!n->joint->tag)
1049 {
1050 int thisDepth = autoEnableDepth;
1051 n->joint->tag = 1;
1052 joint[jcount++] = n->joint;
1053 if (n->body && !n->body->tag)
1054 {
1055 if (n->body->flags & dxBodyDisabled)
1056 thisDepth = autoDepth - 1;
1057 if (thisDepth < 0)
1058 continue;
1059 n->body->flags &= ~dxBodyDisabled;
1060 n->body->tag = 1;
1061 autostack[stacksize] = thisDepth;
1062 stack[stacksize++] = n->body;
1063 }
1064 }
1065 }
1066 dIASSERT (stacksize <= world->nb);
1067 dIASSERT (stacksize <= world->nj);
1068 }
1069
1070 // now do something with body and joint lists
1071 dInternalStepIslandFast (world, body, bcount, joint, jcount, stepsize, maxiterations);
1072
1073 // what we've just done may have altered the body/joint tag values.
1074 // we must make sure that these tags are nonzero.
1075 // also make sure all bodies are in the enabled state.
1076 int i;
1077 for (i = 0; i < bcount; i++)
1078 {
1079 body[i]->tag = 1;
1080 body[i]->flags &= ~dxBodyDisabled;
1081 }
1082 for (i = 0; i < jcount; i++)
1083 joint[i]->tag = 1;
1084
1085 tbcount += bcount;
1086 tjcount += jcount;
1087 }
1088
1089#ifdef TIMING
1090 dMessage(0, "Total joints processed: %i, bodies: %i", tjcount, tbcount);
1091#endif
1092
1093 // if debugging, check that all objects (except for disabled bodies,
1094 // unconnected joints, and joints that are connected to disabled bodies)
1095 // were tagged.
1096# ifndef dNODEBUG
1097 for (b = world->firstbody; b; b = (dxBody *) b->next)
1098 {
1099 if (b->flags & dxBodyDisabled)
1100 {
1101 if (b->tag)
1102 dDebug (0, "disabled body tagged");
1103 }
1104 else
1105 {
1106 if (!b->tag)
1107 dDebug (0, "enabled body not tagged");
1108 }
1109 }
1110 for (j = world->firstjoint; j; j = (dxJoint *) j->next)
1111 {
1112 if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled) == 0) || (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled) == 0))
1113 {
1114 if (!j->tag)
1115 dDebug (0, "attached enabled joint not tagged");
1116 }
1117 else
1118 {
1119 if (j->tag)
1120 dDebug (0, "unattached or disabled joint tagged");
1121 }
1122 }
1123# endif
1124
1125# ifdef TIMING
1126 dTimerEnd ();
1127 dTimerReport (stdout, 1);
1128# endif
1129}
1130
1131#endif
1132
1133
1134void dWorldStepFast1 (dWorldID w, dReal stepsize, int maxiterations)
1135{
1136 dUASSERT (w, "bad world argument");
1137 dUASSERT (stepsize > 0, "stepsize must be > 0");
1138 processIslandsFast (w, stepsize, maxiterations);
1139}
diff --git a/libraries/ode-0.9/ode/src/testing.cpp b/libraries/ode-0.9/ode/src/testing.cpp
deleted file mode 100644
index a22f865..0000000
--- a/libraries/ode-0.9/ode/src/testing.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include <ode/config.h>
24#include <ode/misc.h>
25#include <ode/memory.h>
26#include "testing.h"
27
28#ifdef dDOUBLE
29static const dReal tol = 1.0e-9;
30#else
31static const dReal tol = 1.0e-5f;
32#endif
33
34
35// matrix header on the stack
36
37struct dMatrixComparison::dMatInfo {
38 int n,m; // size of matrix
39 char name[128]; // name of the matrix
40 dReal *data; // matrix data
41 int size; // size of `data'
42};
43
44
45
46dMatrixComparison::dMatrixComparison()
47{
48 afterfirst = 0;
49 index = 0;
50}
51
52
53dMatrixComparison::~dMatrixComparison()
54{
55 reset();
56}
57
58
59dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
60 char *name, ...)
61{
62 if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
63 int num = n*dPAD(m);
64
65 if (afterfirst==0) {
66 dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
67 mi->n = n;
68 mi->m = m;
69 mi->size = num * sizeof(dReal);
70 mi->data = (dReal*) dAlloc (mi->size);
71 memcpy (mi->data,A,mi->size);
72
73 va_list ap;
74 va_start (ap,name);
75 vsprintf (mi->name,name,ap);
76 if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
77
78 mat.push (mi);
79 return 0;
80 }
81 else {
82 if (lower_tri && n != m)
83 dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
84 if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
85 dMatInfo *mp = mat[index];
86 index++;
87
88 dMatInfo mi;
89 va_list ap;
90 va_start (ap,name);
91 vsprintf (mi.name,name,ap);
92 if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
93
94 if (strcmp(mp->name,mi.name) != 0)
95 dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
96 mp->name,mi.name);
97 if (mp->n != n || mp->m != m)
98 dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
99 mp->n,mp->m,n,m);
100
101 dReal maxdiff;
102 if (lower_tri) {
103 maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
104 }
105 else {
106 maxdiff = dMaxDifference (A,mp->data,n,m);
107 }
108 if (maxdiff > tol)
109 dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
110 "error=%.4e)",n,m,mi.name,maxdiff);
111 return maxdiff;
112 }
113}
114
115
116void dMatrixComparison::end()
117{
118 if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
119 afterfirst = 1;
120 index = 0;
121}
122
123
124void dMatrixComparison::reset()
125{
126 for (int i=0; i<mat.size(); i++) {
127 dFree (mat[i]->data,mat[i]->size);
128 dFree (mat[i],sizeof(dMatInfo));
129 }
130 mat.setSize (0);
131 afterfirst = 0;
132 index = 0;
133}
134
135
136void dMatrixComparison::dump()
137{
138 for (int i=0; i<mat.size(); i++)
139 printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
140}
141
142//****************************************************************************
143// unit test
144
145#include <setjmp.h>
146
147static jmp_buf jump_buffer;
148
149static void myDebug (int num, const char *msg, va_list ap)
150{
151 // printf ("(Error %d: ",num);
152 // vprintf (msg,ap);
153 // printf (")\n");
154 longjmp (jump_buffer,1);
155}
156
157
158extern "C" ODE_API void dTestMatrixComparison()
159{
160 volatile int i;
161 printf ("dTestMatrixComparison()\n");
162 dMessageFunction *orig_debug = dGetDebugHandler();
163
164 dMatrixComparison mc;
165 dReal A[50*50];
166
167 // make first sequence
168 unsigned long seed = dRandGetSeed();
169 for (i=1; i<49; i++) {
170 dMakeRandomMatrix (A,i,i+1,1.0);
171 mc.nextMatrix (A,i,i+1,0,"A%d",i);
172 }
173 mc.end();
174
175 //mc.dump();
176
177 // test identical sequence
178 dSetDebugHandler (&myDebug);
179 dRandSetSeed (seed);
180 if (setjmp (jump_buffer)) {
181 printf ("\tFAILED (1)\n");
182 }
183 else {
184 for (i=1; i<49; i++) {
185 dMakeRandomMatrix (A,i,i+1,1.0);
186 mc.nextMatrix (A,i,i+1,0,"A%d",i);
187 }
188 mc.end();
189 printf ("\tpassed (1)\n");
190 }
191 dSetDebugHandler (orig_debug);
192
193 // test broken sequences (with matrix error)
194 dRandSetSeed (seed);
195 volatile int passcount = 0;
196 for (i=1; i<49; i++) {
197 if (setjmp (jump_buffer)) {
198 passcount++;
199 }
200 else {
201 dSetDebugHandler (&myDebug);
202 dMakeRandomMatrix (A,i,i+1,1.0);
203 A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
204 mc.nextMatrix (A,i,i+1,0,"A%d",i);
205 dSetDebugHandler (orig_debug);
206 }
207 }
208 mc.end();
209 printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
210
211 // test broken sequences (with name error)
212 dRandSetSeed (seed);
213 passcount = 0;
214 for (i=1; i<49; i++) {
215 if (setjmp (jump_buffer)) {
216 passcount++;
217 }
218 else {
219 dSetDebugHandler (&myDebug);
220 dMakeRandomMatrix (A,i,i+1,1.0);
221 mc.nextMatrix (A,i,i+1,0,"B%d",i);
222 dSetDebugHandler (orig_debug);
223 }
224 }
225 mc.end();
226 printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
227
228 // test identical sequence again
229 dSetDebugHandler (&myDebug);
230 dRandSetSeed (seed);
231 if (setjmp (jump_buffer)) {
232 printf ("\tFAILED (4)\n");
233 }
234 else {
235 for (i=1; i<49; i++) {
236 dMakeRandomMatrix (A,i,i+1,1.0);
237 mc.nextMatrix (A,i,i+1,0,"A%d",i);
238 }
239 mc.end();
240 printf ("\tpassed (4)\n");
241 }
242 dSetDebugHandler (orig_debug);
243}
diff --git a/libraries/ode-0.9/ode/src/testing.h b/libraries/ode-0.9/ode/src/testing.h
deleted file mode 100644
index 4d19ff3..0000000
--- a/libraries/ode-0.9/ode/src/testing.h
+++ /dev/null
@@ -1,65 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/* stuff used for testing */
24
25#ifndef _ODE_TESTING_H_
26#define _ODE_TESTING_H_
27
28#include <ode/common.h>
29#include "array.h"
30
31
32// compare a sequence of named matrices/vectors, i.e. to make sure that two
33// different pieces of code are giving the same results.
34
35class dMatrixComparison {
36 struct dMatInfo;
37 dArray<dMatInfo*> mat;
38 int afterfirst,index;
39
40public:
41 dMatrixComparison();
42 ~dMatrixComparison();
43
44 dReal nextMatrix (dReal *A, int n, int m, int lower_tri, char *name, ...);
45 // add a new n*m matrix A to the sequence. the name of the matrix is given
46 // by the printf-style arguments (name,...). if this is the first sequence
47 // then this object will simply record the matrices and return 0.
48 // if this the second or subsequent sequence then this object will compare
49 // the matrices with the first sequence, and report any differences.
50 // the matrix error will be returned. if `lower_tri' is 1 then only the
51 // lower triangle of the matrix (including the diagonal) will be compared
52 // (the matrix must be square).
53
54 void end();
55 // end a sequence.
56
57 void reset();
58 // restarts the object, so the next sequence will be the first sequence.
59
60 void dump();
61 // print out info about all the matrices in the sequence
62};
63
64
65#endif
diff --git a/libraries/ode-0.9/ode/src/timer.cpp b/libraries/ode-0.9/ode/src/timer.cpp
deleted file mode 100644
index f754bf1..0000000
--- a/libraries/ode-0.9/ode/src/timer.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25TODO
26----
27
28* gettimeofday() and the pentium time stamp counter return the real time,
29 not the process time. fix this somehow!
30
31*/
32
33#include <ode/common.h>
34#include <ode/timer.h>
35
36// misc defines
37#define ALLOCA dALLOCA16
38
39//****************************************************************************
40// implementation for windows based on the multimedia performance counter.
41
42#ifdef WIN32
43
44#include "windows.h"
45
46static inline void getClockCount (unsigned long cc[2])
47{
48 LARGE_INTEGER a;
49 QueryPerformanceCounter (&a);
50 cc[0] = a.LowPart;
51 cc[1] = a.HighPart;
52}
53
54
55static inline void serialize()
56{
57}
58
59
60static inline double loadClockCount (unsigned long cc[2])
61{
62 LARGE_INTEGER a;
63 a.LowPart = cc[0];
64 a.HighPart = cc[1];
65 return double(a.QuadPart);
66}
67
68
69double dTimerResolution()
70{
71 return 1.0/dTimerTicksPerSecond();
72}
73
74
75double dTimerTicksPerSecond()
76{
77 static int query=0;
78 static double hz=0.0;
79 if (!query) {
80 LARGE_INTEGER a;
81 QueryPerformanceFrequency (&a);
82 hz = double(a.QuadPart);
83 query = 1;
84 }
85 return hz;
86}
87
88#endif
89
90//****************************************************************************
91// implementation based on the pentium time stamp counter. the timer functions
92// can be serializing or non-serializing. serializing will ensure that all
93// instructions have executed and data has been written back before the cpu
94// time stamp counter is read. the CPUID instruction is used to serialize.
95
96#if defined(PENTIUM) && !defined(WIN32)
97
98// we need to know the clock rate so that the timing function can report
99// accurate times. this number only needs to be set accurately if we're
100// doing performance tests and care about real-world time numbers - otherwise,
101// just ignore this. i have not worked out how to determine this number
102// automatically yet.
103
104#define PENTIUM_HZ (500e6)
105
106static inline void getClockCount (unsigned long cc[2])
107{
108#ifndef X86_64_SYSTEM
109 asm volatile (
110 "rdtsc\n"
111 "movl %%eax,(%%esi)\n"
112 "movl %%edx,4(%%esi)\n"
113 : : "S" (cc) : "%eax","%edx","cc","memory");
114#else
115 asm volatile (
116 "rdtsc\n"
117 "movl %%eax,(%%rsi)\n"
118 "movl %%edx,4(%%rsi)\n"
119 : : "S" (cc) : "%eax","%edx","cc","memory");
120#endif
121}
122
123
124static inline void serialize()
125{
126#ifndef X86_64_SYSTEM
127 asm volatile (
128 "mov $0,%%eax\n"
129 "push %%ebx\n"
130 "cpuid\n"
131 "pop %%ebx\n"
132 : : : "%eax","%ecx","%edx","cc","memory");
133#else
134 asm volatile (
135 "mov $0,%%rax\n"
136 "push %%rbx\n"
137 "cpuid\n"
138 "pop %%rbx\n"
139 : : : "%rax","%rcx","%rdx","cc","memory");
140#endif
141}
142
143
144static inline double loadClockCount (unsigned long a[2])
145{
146 double ret;
147#ifndef X86_64_SYSTEM
148 asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
149 "cc","memory");
150#else
151 asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
152 "cc","memory");
153#endif
154 return ret;
155}
156
157
158double dTimerResolution()
159{
160 return 1.0/PENTIUM_HZ;
161}
162
163
164double dTimerTicksPerSecond()
165{
166 return PENTIUM_HZ;
167}
168
169#endif
170
171//****************************************************************************
172// otherwise, do the implementation based on gettimeofday().
173
174#if !defined(PENTIUM) && !defined(WIN32)
175
176#ifndef macintosh
177
178#include <sys/time.h>
179#include <unistd.h>
180
181
182static inline void getClockCount (unsigned long cc[2])
183{
184 struct timeval tv;
185 gettimeofday (&tv,0);
186 cc[0] = tv.tv_usec;
187 cc[1] = tv.tv_sec;
188}
189
190#else // macintosh
191
192#include <MacTypes.h>
193#include <Timer.h>
194
195static inline void getClockCount (unsigned long cc[2])
196{
197 UnsignedWide ms;
198 Microseconds (&ms);
199 cc[1] = ms.lo / 1000000;
200 cc[0] = ms.lo - ( cc[1] * 1000000 );
201}
202
203#endif
204
205
206static inline void serialize()
207{
208}
209
210
211static inline double loadClockCount (unsigned long a[2])
212{
213 return a[1]*1.0e6 + a[0];
214}
215
216
217double dTimerResolution()
218{
219 unsigned long cc1[2],cc2[2];
220 getClockCount (cc1);
221 do {
222 getClockCount (cc2);
223 }
224 while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
225 do {
226 getClockCount (cc1);
227 }
228 while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
229 double t1 = loadClockCount (cc1);
230 double t2 = loadClockCount (cc2);
231 return (t1-t2) / dTimerTicksPerSecond();
232}
233
234
235double dTimerTicksPerSecond()
236{
237 return 1000000;
238}
239
240#endif
241
242//****************************************************************************
243// stop watches
244
245void dStopwatchReset (dStopwatch *s)
246{
247 s->time = 0;
248 s->cc[0] = 0;
249 s->cc[1] = 0;
250}
251
252
253void dStopwatchStart (dStopwatch *s)
254{
255 serialize();
256 getClockCount (s->cc);
257}
258
259
260void dStopwatchStop (dStopwatch *s)
261{
262 unsigned long cc[2];
263 serialize();
264 getClockCount (cc);
265 double t1 = loadClockCount (s->cc);
266 double t2 = loadClockCount (cc);
267 s->time += t2-t1;
268}
269
270
271double dStopwatchTime (dStopwatch *s)
272{
273 return s->time / dTimerTicksPerSecond();
274}
275
276//****************************************************************************
277// code timers
278
279// maximum number of events to record
280#define MAXNUM 100
281
282static int num = 0; // number of entries used in event array
283static struct {
284 unsigned long cc[2]; // clock counts
285 double total_t; // total clocks used in this slot.
286 double total_p; // total percentage points used in this slot.
287 int count; // number of times this slot has been updated.
288 char *description; // pointer to static string
289} event[MAXNUM];
290
291
292// make sure all slot totals and counts reset to 0 at start
293
294static void initSlots()
295{
296 static int initialized=0;
297 if (!initialized) {
298 for (int i=0; i<MAXNUM; i++) {
299 event[i].count = 0;
300 event[i].total_t = 0;
301 event[i].total_p = 0;
302 }
303 initialized = 1;
304 }
305}
306
307
308void dTimerStart (const char *description)
309{
310 initSlots();
311 event[0].description = const_cast<char*> (description);
312 num = 1;
313 serialize();
314 getClockCount (event[0].cc);
315}
316
317
318void dTimerNow (const char *description)
319{
320 if (num < MAXNUM) {
321 // do not serialize
322 getClockCount (event[num].cc);
323 event[num].description = const_cast<char*> (description);
324 num++;
325 }
326}
327
328
329void dTimerEnd()
330{
331 if (num < MAXNUM) {
332 serialize();
333 getClockCount (event[num].cc);
334 event[num].description = "TOTAL";
335 num++;
336 }
337}
338
339//****************************************************************************
340// print report
341
342static void fprintDoubleWithPrefix (FILE *f, double a, char *fmt)
343{
344 if (a >= 0.999999) {
345 fprintf (f,fmt,a);
346 return;
347 }
348 a *= 1000.0;
349 if (a >= 0.999999) {
350 fprintf (f,fmt,a);
351 fprintf (f,"m");
352 return;
353 }
354 a *= 1000.0;
355 if (a >= 0.999999) {
356 fprintf (f,fmt,a);
357 fprintf (f,"u");
358 return;
359 }
360 a *= 1000.0;
361 fprintf (f,fmt,a);
362 fprintf (f,"n");
363}
364
365
366void dTimerReport (FILE *fout, int average)
367{
368 int i;
369 size_t maxl;
370 double ccunit = 1.0/dTimerTicksPerSecond();
371 fprintf (fout,"\nTimer Report (");
372 fprintDoubleWithPrefix (fout,ccunit,"%.2f ");
373 fprintf (fout,"s resolution)\n------------\n");
374 if (num < 1) return;
375
376 // get maximum description length
377 maxl = 0;
378 for (i=0; i<num; i++) {
379 size_t l = strlen (event[i].description);
380 if (l > maxl) maxl = l;
381 }
382
383 // calculate total time
384 double t1 = loadClockCount (event[0].cc);
385 double t2 = loadClockCount (event[num-1].cc);
386 double total = t2 - t1;
387 if (total <= 0) total = 1;
388
389 // compute time difference for all slots except the last one. update totals
390 double *times = (double*) ALLOCA (num * sizeof(double));
391 for (i=0; i < (num-1); i++) {
392 double t1 = loadClockCount (event[i].cc);
393 double t2 = loadClockCount (event[i+1].cc);
394 times[i] = t2 - t1;
395 event[i].count++;
396 event[i].total_t += times[i];
397 event[i].total_p += times[i]/total * 100.0;
398 }
399
400 // print report (with optional averages)
401 for (i=0; i<num; i++) {
402 double t,p;
403 if (i < (num-1)) {
404 t = times[i];
405 p = t/total * 100.0;
406 }
407 else {
408 t = total;
409 p = 100.0;
410 }
411 fprintf (fout,"%-*s %7.2fms %6.2f%%",maxl,event[i].description,
412 t*ccunit * 1000.0, p);
413 if (average && i < (num-1)) {
414 fprintf (fout," (avg %7.2fms %6.2f%%)",
415 (event[i].total_t / event[i].count)*ccunit * 1000.0,
416 event[i].total_p / event[i].count);
417 }
418 fprintf (fout,"\n");
419 }
420 fprintf (fout,"\n");
421}
diff --git a/libraries/ode-0.9/ode/src/util.cpp b/libraries/ode-0.9/ode/src/util.cpp
deleted file mode 100644
index c8d6230..0000000
--- a/libraries/ode-0.9/ode/src/util.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#include "ode/ode.h"
24#include "objects.h"
25#include "joint.h"
26#include "util.h"
27
28#define ALLOCA dALLOCA16
29
30//****************************************************************************
31// Auto disabling
32
33void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize)
34{
35 dxBody *bb;
36 for ( bb=world->firstbody; bb; bb=(dxBody*)bb->next )
37 {
38 // don't freeze objects mid-air (patch 1586738)
39 if ( bb->firstjoint == NULL ) continue;
40
41 // nothing to do unless this body is currently enabled and has
42 // the auto-disable flag set
43 if ( (bb->flags & (dxBodyAutoDisable|dxBodyDisabled)) != dxBodyAutoDisable ) continue;
44
45 // if sampling / threshold testing is disabled, we can never sleep.
46 if ( bb->adis.average_samples == 0 ) continue;
47
48 //
49 // see if the body is idle
50 //
51
52#ifndef dNODEBUG
53 // sanity check
54 if ( bb->average_counter >= bb->adis.average_samples )
55 {
56 dUASSERT( bb->average_counter < bb->adis.average_samples, "buffer overflow" );
57
58 // something is going wrong, reset the average-calculations
59 bb->average_ready = 0; // not ready for average calculation
60 bb->average_counter = 0; // reset the buffer index
61 }
62#endif // dNODEBUG
63
64 // sample the linear and angular velocity
65 bb->average_lvel_buffer[bb->average_counter][0] = bb->lvel[0];
66 bb->average_lvel_buffer[bb->average_counter][1] = bb->lvel[1];
67 bb->average_lvel_buffer[bb->average_counter][2] = bb->lvel[2];
68 bb->average_avel_buffer[bb->average_counter][0] = bb->avel[0];
69 bb->average_avel_buffer[bb->average_counter][1] = bb->avel[1];
70 bb->average_avel_buffer[bb->average_counter][2] = bb->avel[2];
71 bb->average_counter++;
72
73 // buffer ready test
74 if ( bb->average_counter >= bb->adis.average_samples )
75 {
76 bb->average_counter = 0; // fill the buffer from the beginning
77 bb->average_ready = 1; // this body is ready now for average calculation
78 }
79
80 int idle = 0; // Assume it's in motion unless we have samples to disprove it.
81
82 // enough samples?
83 if ( bb->average_ready )
84 {
85 idle = 1; // Initial assumption: IDLE
86
87 // the sample buffers are filled and ready for calculation
88 dVector3 average_lvel, average_avel;
89
90 // Store first velocity samples
91 average_lvel[0] = bb->average_lvel_buffer[0][0];
92 average_avel[0] = bb->average_avel_buffer[0][0];
93 average_lvel[1] = bb->average_lvel_buffer[0][1];
94 average_avel[1] = bb->average_avel_buffer[0][1];
95 average_lvel[2] = bb->average_lvel_buffer[0][2];
96 average_avel[2] = bb->average_avel_buffer[0][2];
97
98 // If we're not in "instantaneous mode"
99 if ( bb->adis.average_samples > 1 )
100 {
101 // add remaining velocities together
102 for ( unsigned int i = 1; i < bb->adis.average_samples; ++i )
103 {
104 average_lvel[0] += bb->average_lvel_buffer[i][0];
105 average_avel[0] += bb->average_avel_buffer[i][0];
106 average_lvel[1] += bb->average_lvel_buffer[i][1];
107 average_avel[1] += bb->average_avel_buffer[i][1];
108 average_lvel[2] += bb->average_lvel_buffer[i][2];
109 average_avel[2] += bb->average_avel_buffer[i][2];
110 }
111
112 // make average
113 dReal r1 = dReal( 1.0 ) / dReal( bb->adis.average_samples );
114
115 average_lvel[0] *= r1;
116 average_avel[0] *= r1;
117 average_lvel[1] *= r1;
118 average_avel[1] *= r1;
119 average_lvel[2] *= r1;
120 average_avel[2] *= r1;
121 }
122
123 // threshold test
124 dReal av_lspeed, av_aspeed;
125 av_lspeed = dDOT( average_lvel, average_lvel );
126 if ( av_lspeed > bb->adis.linear_average_threshold )
127 {
128 idle = 0; // average linear velocity is too high for idle
129 }
130 else
131 {
132 av_aspeed = dDOT( average_avel, average_avel );
133 if ( av_aspeed > bb->adis.angular_average_threshold )
134 {
135 idle = 0; // average angular velocity is too high for idle
136 }
137 }
138 }
139
140 // if it's idle, accumulate steps and time.
141 // these counters won't overflow because this code doesn't run for disabled bodies.
142 if (idle) {
143 bb->adis_stepsleft--;
144 bb->adis_timeleft -= stepsize;
145 }
146 else {
147 // Reset countdowns
148 bb->adis_stepsleft = bb->adis.idle_steps;
149 bb->adis_timeleft = bb->adis.idle_time;
150 }
151
152 // disable the body if it's idle for a long enough time
153 if ( bb->adis_stepsleft <= 0 && bb->adis_timeleft <= 0 )
154 {
155 bb->flags |= dxBodyDisabled; // set the disable flag
156
157 // disabling bodies should also include resetting the velocity
158 // should prevent jittering in big "islands"
159 bb->lvel[0] = 0;
160 bb->lvel[1] = 0;
161 bb->lvel[2] = 0;
162 bb->avel[0] = 0;
163 bb->avel[1] = 0;
164 bb->avel[2] = 0;
165 }
166 }
167}
168
169
170//****************************************************************************
171// body rotation
172
173// return sin(x)/x. this has a singularity at 0 so special handling is needed
174// for small arguments.
175
176static inline dReal sinc (dReal x)
177{
178 // if |x| < 1e-4 then use a taylor series expansion. this two term expansion
179 // is actually accurate to one LS bit within this range if double precision
180 // is being used - so don't worry!
181 if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667);
182 else return dSin(x)/x;
183}
184
185
186// given a body b, apply its linear and angular rotation over the time
187// interval h, thereby adjusting its position and orientation.
188
189void dxStepBody (dxBody *b, dReal h)
190{
191 int j;
192
193 // handle linear velocity
194 for (j=0; j<3; j++) b->posr.pos[j] += h * b->lvel[j];
195
196 if (b->flags & dxBodyFlagFiniteRotation) {
197 dVector3 irv; // infitesimal rotation vector
198 dQuaternion q; // quaternion for finite rotation
199
200 if (b->flags & dxBodyFlagFiniteRotationAxis) {
201 // split the angular velocity vector into a component along the finite
202 // rotation axis, and a component orthogonal to it.
203 dVector3 frv; // finite rotation vector
204 dReal k = dDOT (b->finite_rot_axis,b->avel);
205 frv[0] = b->finite_rot_axis[0] * k;
206 frv[1] = b->finite_rot_axis[1] * k;
207 frv[2] = b->finite_rot_axis[2] * k;
208 irv[0] = b->avel[0] - frv[0];
209 irv[1] = b->avel[1] - frv[1];
210 irv[2] = b->avel[2] - frv[2];
211
212 // make a rotation quaternion q that corresponds to frv * h.
213 // compare this with the full-finite-rotation case below.
214 h *= REAL(0.5);
215 dReal theta = k * h;
216 q[0] = dCos(theta);
217 dReal s = sinc(theta) * h;
218 q[1] = frv[0] * s;
219 q[2] = frv[1] * s;
220 q[3] = frv[2] * s;
221 }
222 else {
223 // make a rotation quaternion q that corresponds to w * h
224 dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
225 b->avel[2]*b->avel[2]);
226 h *= REAL(0.5);
227 dReal theta = wlen * h;
228 q[0] = dCos(theta);
229 dReal s = sinc(theta) * h;
230 q[1] = b->avel[0] * s;
231 q[2] = b->avel[1] * s;
232 q[3] = b->avel[2] * s;
233 }
234
235 // do the finite rotation
236 dQuaternion q2;
237 dQMultiply0 (q2,q,b->q);
238 for (j=0; j<4; j++) b->q[j] = q2[j];
239
240 // do the infitesimal rotation if required
241 if (b->flags & dxBodyFlagFiniteRotationAxis) {
242 dReal dq[4];
243 dWtoDQ (irv,b->q,dq);
244 for (j=0; j<4; j++) b->q[j] += h * dq[j];
245 }
246 }
247 else {
248 // the normal way - do an infitesimal rotation
249 dReal dq[4];
250 dWtoDQ (b->avel,b->q,dq);
251 for (j=0; j<4; j++) b->q[j] += h * dq[j];
252 }
253
254 // normalize the quaternion and convert it to a rotation matrix
255 dNormalize4 (b->q);
256 dQtoR (b->q,b->posr.R);
257
258 // notify all attached geoms that this body has moved
259 for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
260 dGeomMoved (geom);
261}
262
263//****************************************************************************
264// island processing
265
266// this groups all joints and bodies in a world into islands. all objects
267// in an island are reachable by going through connected bodies and joints.
268// each island can be simulated separately.
269// note that joints that are not attached to anything will not be included
270// in any island, an so they do not affect the simulation.
271//
272// this function starts new island from unvisited bodies. however, it will
273// never start a new islands from a disabled body. thus islands of disabled
274// bodies will not be included in the simulation. disabled bodies are
275// re-enabled if they are found to be part of an active island.
276
277void dxProcessIslands (dxWorld *world, dReal stepsize, dstepper_fn_t stepper)
278{
279 dxBody *b,*bb,**body;
280 dxJoint *j,**joint;
281
282 // nothing to do if no bodies
283 if (world->nb <= 0) return;
284
285 // handle auto-disabling of bodies
286 dInternalHandleAutoDisabling (world,stepsize);
287
288 // make arrays for body and joint lists (for a single island) to go into
289 body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*));
290 joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*));
291 int bcount = 0; // number of bodies in `body'
292 int jcount = 0; // number of joints in `joint'
293
294 // set all body/joint tags to 0
295 for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0;
296 for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0;
297
298 // allocate a stack of unvisited bodies in the island. the maximum size of
299 // the stack can be the lesser of the number of bodies or joints, because
300 // new bodies are only ever added to the stack by going through untagged
301 // joints. all the bodies in the stack must be tagged!
302 int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
303 dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*));
304
305 for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) {
306 // get bb = the next enabled, untagged body, and tag it
307 if (bb->tag || (bb->flags & dxBodyDisabled)) continue;
308 bb->tag = 1;
309
310 // tag all bodies and joints starting from bb.
311 int stacksize = 0;
312 b = bb;
313 body[0] = bb;
314 bcount = 1;
315 jcount = 0;
316 goto quickstart;
317 while (stacksize > 0) {
318 b = stack[--stacksize]; // pop body off stack
319 body[bcount++] = b; // put body on body list
320 quickstart:
321
322 // traverse and tag all body's joints, add untagged connected bodies
323 // to stack
324 for (dxJointNode *n=b->firstjoint; n; n=n->next) {
325 if (!n->joint->tag) {
326 n->joint->tag = 1;
327 joint[jcount++] = n->joint;
328 if (n->body && !n->body->tag) {
329 n->body->tag = 1;
330 stack[stacksize++] = n->body;
331 }
332 }
333 }
334 dIASSERT(stacksize <= world->nb);
335 dIASSERT(stacksize <= world->nj);
336 }
337
338 // now do something with body and joint lists
339 stepper (world,body,bcount,joint,jcount,stepsize);
340
341 // what we've just done may have altered the body/joint tag values.
342 // we must make sure that these tags are nonzero.
343 // also make sure all bodies are in the enabled state.
344 int i;
345 for (i=0; i<bcount; i++) {
346 body[i]->tag = 1;
347 body[i]->flags &= ~dxBodyDisabled;
348 }
349 for (i=0; i<jcount; i++) joint[i]->tag = 1;
350 }
351
352 // if debugging, check that all objects (except for disabled bodies,
353 // unconnected joints, and joints that are connected to disabled bodies)
354 // were tagged.
355# ifndef dNODEBUG
356 for (b=world->firstbody; b; b=(dxBody*)b->next) {
357 if (b->flags & dxBodyDisabled) {
358 if (b->tag) dDebug (0,"disabled body tagged");
359 }
360 else {
361 if (!b->tag) dDebug (0,"enabled body not tagged");
362 }
363 }
364 for (j=world->firstjoint; j; j=(dxJoint*)j->next) {
365 if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) ||
366 (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) {
367 if (!j->tag) dDebug (0,"attached enabled joint not tagged");
368 }
369 else {
370 if (j->tag) dDebug (0,"unattached or disabled joint tagged");
371 }
372 }
373# endif
374}
diff --git a/libraries/ode-0.9/ode/src/util.h b/libraries/ode-0.9/ode/src/util.h
deleted file mode 100644
index a8e6390..0000000
--- a/libraries/ode-0.9/ode/src/util.h
+++ /dev/null
@@ -1,38 +0,0 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23#ifndef _ODE_UTIL_H_
24#define _ODE_UTIL_H_
25
26#include "objects.h"
27
28
29void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize);
30void dxStepBody (dxBody *b, dReal h);
31
32typedef void (*dstepper_fn_t) (dxWorld *world, dxBody * const *body, int nb,
33 dxJoint * const *_joint, int nj, dReal stepsize);
34
35void dxProcessIslands (dxWorld *world, dReal stepsize, dstepper_fn_t stepper);
36
37
38#endif