Index: /d-collide/tags/1.0.0/cmake/modules/FindLib3ds.cmake
===================================================================
--- /d-collide/tags/1.0.0/cmake/modules/FindLib3ds.cmake (revision 1681)
+++ /d-collide/tags/1.0.0/cmake/modules/FindLib3ds.cmake (revision 1681)
@@ -0,0 +1,37 @@
+# find lib3ds includes and library
+#
+# LIB3DS_INCLUDE_DIR - where the lib3ds directory containing the headers can be
+#                      found
+# LIB3DS_LIBRARY     - full path to the lib3ds library
+# LIB3DS_FOUND       - TRUE if lib3ds was found
+
+FIND_PATH(LIB3DS_INCLUDE_DIR lib3ds/file.h
+    /usr/include
+    /usr/local/include
+    $ENV{INCLUDE}
+)
+FIND_LIBRARY(LIB3DS_LIBRARY NAMES 3ds lib3ds)
+
+IF(LIB3DS_INCLUDE_DIR)
+    MESSAGE(STATUS "Found lib3ds include dir: ${LIB3DS_INCLUDE_DIR}")
+ELSE(LIB3DS_INCLUDE_DIR)
+    MESSAGE(STATUS "Could NOT find lib3ds headers.")
+ENDIF(LIB3DS_INCLUDE_DIR)
+
+IF(LIB3DS_LIBRARY)
+    MESSAGE(STATUS "Found lib3ds library: ${LIB3DS_LIBRARY}")
+ELSE(LIB3DS_LIBRARY)
+    MESSAGE(STATUS "Could NOT find lib3ds library.")
+ENDIF(LIB3DS_LIBRARY)
+
+
+IF(LIB3DS_INCLUDE_DIR AND LIB3DS_LIBRARY)
+    SET(LIB3DS_FOUND TRUE)
+ELSE(LIB3DS_INCLUDE_DIR AND LIB3DS_LIBRARY)
+    SET(LIB3DS_FOUND FALSE)
+    IF(Lib3ds_FIND_REQUIRED)
+        MESSAGE(FATAL_ERROR "Could not find lib3ds. Please install lib3ds (http://lib3ds.sourceforge.net)")
+    ENDIF(Lib3ds_FIND_REQUIRED)
+ENDIF(LIB3DS_INCLUDE_DIR AND LIB3DS_LIBRARY)
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/cmake/modules/FindODE.cmake
===================================================================
--- /d-collide/tags/1.0.0/cmake/modules/FindODE.cmake (revision 1706)
+++ /d-collide/tags/1.0.0/cmake/modules/FindODE.cmake (revision 1706)
@@ -0,0 +1,49 @@
+# find ODE (Open Dynamics Engine) includes and library
+#
+# ODE_INCLUDE_DIR - where the directory containing the ODE headers can be
+#                   found
+# ODE_LIBRARY     - full path to the ODE library
+# ODE_FOUND       - TRUE if ODE was found
+
+IF (NOT ODE_FOUND)
+
+    FIND_PATH(ODE_INCLUDE_DIR ode/ode.h
+        /usr/include
+        /usr/local/include
+        $ENV{OGRE_HOME}/include # OGRE SDK on WIN32
+        $ENV{INCLUDE}
+    )
+    FIND_LIBRARY(ODE_LIBRARY
+        NAMES ode
+        PATHS
+        /usr/lib
+        /usr/local/lib
+        $ENV{OGRE_HOME}/lib # OGRE SDK on WIN32
+    )
+    
+    
+    IF(ODE_INCLUDE_DIR)
+        MESSAGE(STATUS "Found ODE include dir: ${ODE_INCLUDE_DIR}")
+    ELSE(ODE_INCLUDE_DIR)
+        MESSAGE(STATUS "Could NOT find ODE headers.")
+    ENDIF(ODE_INCLUDE_DIR)
+    
+    IF(ODE_LIBRARY)
+        MESSAGE(STATUS "Found ODE library: ${ODE_LIBRARY}")
+    ELSE(ODE_LIBRARY)
+        MESSAGE(STATUS "Could NOT find ODE library.")
+    ENDIF(ODE_LIBRARY)
+    
+    
+    IF(ODE_INCLUDE_DIR AND ODE_LIBRARY)
+        SET(ODE_FOUND TRUE CACHE STRING "Whether ODE was found or not")
+    ELSE(ODE_INCLUDE_DIR AND ODE_LIBRARY)
+        SET(ODE_FOUND FALSE)
+        IF(ODE_FIND_REQUIRED)
+            MESSAGE(FATAL_ERROR "Could not find ODE. Please install ODE (http://www.ode.org)")
+        ENDIF(ODE_FIND_REQUIRED)
+    ENDIF(ODE_INCLUDE_DIR AND ODE_LIBRARY)
+    
+ENDIF (NOT ODE_FOUND)
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/cmake/modules/FindPkgConfig.cmake
===================================================================
--- /d-collide/tags/1.0.0/cmake/modules/FindPkgConfig.cmake (revision 644)
+++ /d-collide/tags/1.0.0/cmake/modules/FindPkgConfig.cmake (revision 644)
@@ -0,0 +1,380 @@
+# - a pkg-config module for CMake
+#
+# Usage:
+#   pkg_check_modules(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
+#     checks for all the given modules
+#
+#   pkg_search_module(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
+#     checks for given modules and uses the first working one
+#
+# When the 'REQUIRED' argument was set, macros will fail with an error
+# when module(s) could not be found
+#
+# It sets the following variables:
+#   PKG_CONFIG_FOUND         ... true iff pkg-config works on the system
+#   PKG_CONFIG_EXECUTABLE    ... pathname of the pkg-config program
+#   <PREFIX>_FOUND           ... set to 1 iff module(s) exist
+#
+# For the following variables two sets of values exist; first one is the
+# common one and has the given PREFIX. The second set contains flags
+# which are given out when pkgconfig was called with the '--static'
+# option.
+#   <XPREFIX>_LIBRARIES      ... only the libraries (w/o the '-l')
+#   <XPREFIX>_LIBRARY_DIRS   ... the paths of the libraries (w/o the '-L')
+#   <XPREFIX>_LDFLAGS        ... all required linker flags
+#   <XPREFIX>_LDFLAGS_OTHERS ... all other linker flags
+#   <XPREFIX>_INCLUDE_DIRS   ... the '-I' preprocessor flags (w/o the '-I')
+#   <XPREFIX>_CFLAGS         ... all required cflags
+#   <XPREFIX>_CFLAGS_OTHERS  ... the other compiler flags
+#
+#   <XPREFIX> = <PREFIX>        for common case
+#   <XPREFIX> = <PREFIX>_STATIC for static linking
+#
+# There are some special variables whose prefix depends on the count
+# of given modules. When there is only one module, <PREFIX> stays
+# unchanged. When there are multiple modules, the prefix will be
+# changed to <PREFIX>_<MODNAME>:
+#   <XPREFIX>_VERSION    ... version of the module
+#   <XPREFIX>_PREFIX     ... prefix-directory of the module
+#   <XPREFIX>_INCLUDEDIR ... include-dir of the module
+#   <XPREFIX>_LIBDIR     ... lib-dir of the module
+#
+#   <XPREFIX> = <PREFIX>  when |MODULES| == 1, else
+#   <XPREFIX> = <PREFIX>_<MODNAME>
+#
+# A <MODULE> parameter can have the following formats:
+#   {MODNAME}            ... matches any version
+#   {MODNAME}>={VERSION} ... at least version <VERSION> is required
+#   {MODNAME}={VERSION}  ... exactly version <VERSION> is required
+#   {MODNAME}<={VERSION} ... modules must not be newer than <VERSION>
+#
+# Examples
+#   pkg_check_modules (GLIB2   glib-2.0)
+#
+#   pkg_check_modules (GLIB2   glib-2.0>=2.10)
+#     requires at least version 2.10 of glib2 and defines e.g.
+#       GLIB2_VERSION=2.10.3
+#
+#   pkg_check_modules (FOO     glib-2.0>=2.10 gtk+-2.0)
+#     requires both glib2 and gtk2, and defines e.g.
+#       FOO_glib-2.0_VERSION=2.10.3
+#       FOO_gtk+-2.0_VERSION=2.8.20
+#
+#   pkg_check_modules (XRENDER REQUIRED xrender)
+#     defines e.g.:
+#       XRENDER_LIBRARIES=Xrender;X11
+#       XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
+#
+#   pkg_search_module (BAR     libxml-2.0 libxml2 libxml>=2)
+
+
+# Copyright (C) 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+#
+# Redistribution and use, with or without modification, are permitted
+# provided that the following conditions are met:
+# 
+#    1. Redistributions must retain the above copyright notice, this
+#       list of conditions and the following disclaimer.
+#    2. The name of the author may not be used to endorse or promote
+#       products derived from this software without specific prior
+#       written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+### Common stuff ####
+set(PKG_CONFIG_VERSION 1)
+set(PKG_CONFIG_FOUND   0)
+
+find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable")
+mark_as_advanced(PKG_CONFIG_EXECUTABLE)
+
+if(PKG_CONFIG_EXECUTABLE)
+  set(PKG_CONFIG_FOUND 1)
+endif(PKG_CONFIG_EXECUTABLE)
+
+
+# Unsets the given variables
+macro(_pkgconfig_unset var)
+  set(${var} "" CACHE INTERNAL "")
+endmacro(_pkgconfig_unset)
+
+macro(_pkgconfig_set var value)
+  set(${var} ${value} CACHE INTERNAL "")
+endmacro(_pkgconfig_set)
+
+# Invokes pkgconfig, cleans up the result and sets variables
+macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
+  set(_pkgconfig_invoke_result)
+
+  execute_process(
+    COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist}
+    OUTPUT_VARIABLE _pkgconfig_invoke_result
+    RESULT_VARIABLE _pkgconfig_failed)
+
+  if (_pkgconfig_failed)
+    set(_pkgconfig_${_varname} "")
+    _pkgconfig_unset(${_prefix}_${_varname})
+  else(_pkgconfig_failed)
+    string(REGEX REPLACE "[\r\n]"                  " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+    string(REGEX REPLACE " +$"                     ""  _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+
+    if (NOT ${_regexp} STREQUAL "")
+      string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+    endif(NOT ${_regexp} STREQUAL "")
+
+    separate_arguments(_pkgconfig_invoke_result)
+
+    #message(STATUS "  ${_varname} ... ${_pkgconfig_invoke_result}")
+    set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result})
+    _pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}")
+  endif(_pkgconfig_failed)
+endmacro(_pkgconfig_invoke)
+
+# Invokes pkgconfig two times; once without '--static' and once with
+# '--static'
+macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp)
+  _pkgconfig_invoke("${_pkglist}" ${_prefix}        ${_varname} "${cleanup_regexp}" ${ARGN})
+  _pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static  ${ARGN})
+endmacro(_pkgconfig_invoke_dyn)
+
+# Splits given arguments into options and a package list
+macro(_pkgconfig_parse_options _result _is_req)
+  set(${_is_req} 0)
+  
+  foreach(_pkg ${ARGN})
+    if (_pkg STREQUAL "REQUIRED")
+      set(${_is_req} 1)
+    endif (_pkg STREQUAL "REQUIRED")
+  endforeach(_pkg ${ARGN})
+
+  set(${_result} ${ARGN})
+  list(REMOVE_ITEM ${_result} "REQUIRED")
+endmacro(_pkgconfig_parse_options)
+
+###
+macro(_pkg_check_modules_internal _is_required _is_silent _prefix)
+  _pkgconfig_unset(${_prefix}_FOUND)
+  _pkgconfig_unset(${_prefix}_VERSION)
+  _pkgconfig_unset(${_prefix}_PREFIX)
+  _pkgconfig_unset(${_prefix}_INCLUDEDIR)
+  _pkgconfig_unset(${_prefix}_LIBDIR)
+  _pkgconfig_unset(${_prefix}_LIBS)
+  _pkgconfig_unset(${_prefix}_LIBS_L)
+  _pkgconfig_unset(${_prefix}_LIBS_PATHS)
+  _pkgconfig_unset(${_prefix}_LIBS_OTHER)
+  _pkgconfig_unset(${_prefix}_CFLAGS)
+  _pkgconfig_unset(${_prefix}_CFLAGS_I)
+  _pkgconfig_unset(${_prefix}_CFLAGS_OTHER)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBDIR)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_L)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS)
+  _pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I)
+  _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER)
+
+  # create a better addressable variable of the modules and calculate its size
+  set(_pkg_check_modules_list ${ARGN})
+  list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt)
+
+  if(PKG_CONFIG_EXECUTABLE)
+    # give out status message telling checked module
+    if (NOT ${_is_silent})
+      if (_pkg_check_modules_cnt EQUAL 1)
+        message(STATUS "checking for module '${_pkg_check_modules_list}'")
+      else(_pkg_check_modules_cnt EQUAL 1)
+        message(STATUS "checking for modules '${_pkg_check_modules_list}'")
+      endif(_pkg_check_modules_cnt EQUAL 1)
+    endif(NOT ${_is_silent})
+    
+    set(_pkg_check_modules_packages)
+    set(_pkg_check_modules_failed)
+
+    # iterate through module list and check whether they exist and match the required version
+    foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list})
+      set(_pkg_check_modules_exist_query)
+
+      # check whether version is given
+      if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op   "${_pkg_check_modules_pkg}")
+        string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver  "${_pkg_check_modules_pkg}")
+      else(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
+        set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
+        set(_pkg_check_modules_pkg_op)
+        set(_pkg_check_modules_pkg_ver)
+      endif(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
+
+      # handle the operands
+      if (_pkg_check_modules_pkg_op STREQUAL ">=")
+        list(APPEND _pkg_check_modules_exist_query --atleast-version)
+      endif(_pkg_check_modules_pkg_op STREQUAL ">=")
+
+      if (_pkg_check_modules_pkg_op STREQUAL "=")
+        list(APPEND _pkg_check_modules_exist_query --exact-version)
+      endif(_pkg_check_modules_pkg_op STREQUAL "=")
+      
+      if (_pkg_check_modules_pkg_op STREQUAL "<=")
+        list(APPEND _pkg_check_modules_exist_query --max-version)
+      endif(_pkg_check_modules_pkg_op STREQUAL "<=")
+
+      # create the final query which is of the format:
+      # * --atleast-version <version> <pkg-name>
+      # * --exact-version <version> <pkg-name>      
+      # * --max-version <version> <pkg-name>
+      # * --exists <pkg-name>
+      if (_pkg_check_modules_pkg_op)
+        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}")
+      else(_pkg_check_modules_pkg_op)
+        list(APPEND _pkg_check_modules_exist_query --exists)
+      endif(_pkg_check_modules_pkg_op)
+
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR)
+
+      list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}")
+      list(APPEND _pkg_check_modules_packages    "${_pkg_check_modules_pkg_name}")
+
+      # execute the query
+      execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query}
+        RESULT_VARIABLE _pkgconfig_retval)
+
+      # evaluate result and tell failures
+      if (_pkgconfig_retval)
+        if(NOT ${_is_silent})
+          message(STATUS "  package '${_pkg_check_modules_pkg}' not found")
+        endif(NOT ${_is_silent})
+
+        set(_pkg_check_modules_failed 1)
+      endif(_pkgconfig_retval)
+    endforeach(_pkg_check_modules_pkg)
+
+    if(_pkg_check_modules_failed)
+      # fail when requested
+      if (${_is_required})
+        message(SEND_ERROR "A required package was not found")
+      endif (${_is_required})
+    else(_pkg_check_modules_failed)
+      # when we are here, we checked whether requested modules
+      # exist. Now, go through them and set variables
+      
+      _pkgconfig_set(${_prefix}_FOUND 1)
+      list(LENGTH _pkg_check_modules_packages pkg_count)
+
+      # iterate through all modules again and set individual variables
+      foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages})
+        # handle case when there is only one package required
+        if (pkg_count EQUAL 1)
+          set(_pkg_check_prefix "${_prefix}")
+        else(pkg_count EQUAL 1)
+          set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}")
+        endif(pkg_count EQUAL 1)
+        
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION    ""   --modversion )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX     ""   --variable=prefix )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR ""   --variable=includedir )
+        _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR     ""   --variable=libdir )
+
+        message(STATUS "  found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}")
+      endforeach(_pkg_check_modules_pkg)
+
+      # set variables which are combined for multiple modules
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES           "(^| )-l" --libs-only-l )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS        "(^| )-L" --libs-only-L )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS             ""        --libs )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER       ""        --libs-only-other )
+
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS        "(^| )-I" --cflags-only-I )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS              ""        --cflags )
+      _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER        ""        --cflags-only-other )
+    endif(_pkg_check_modules_failed)
+  else(PKG_CONFIG_EXECUTABLE)
+    if (${_is_required})
+      message(SEND_ERROR "pkg-config tool not found")
+    endif (${_is_required})
+  endif(PKG_CONFIG_EXECUTABLE)
+endmacro(_pkg_check_modules_internal)
+
+###
+### User visible macros start here
+###
+
+###
+macro(pkg_check_modules _prefix _module0)
+  # check cached value
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
+    _pkgconfig_parse_options   (_pkg_modules _pkg_is_required "${_module0}" ${ARGN})
+    _pkg_check_modules_internal("${_pkg_is_required}" 0 "${_prefix}" ${_pkg_modules})
+
+    #_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+  endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
+endmacro(pkg_check_modules)
+
+###
+macro(pkg_search_module _prefix _module0)
+  # check cached value
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
+    set(_pkg_modules_found 0)
+    _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required "${_module0}" ${ARGN})
+
+    message(STATUS "checking for one of the modules '${_pkg_modules_alt}'")
+
+    # iterate through all modules and stop at the first working one.
+    foreach(_pkg_alt ${_pkg_modules_alt})
+      if(NOT _pkg_modules_found)
+        _pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}")
+      endif(NOT _pkg_modules_found)
+
+      if (${_prefix}_FOUND)
+        set(_pkg_modules_found 1)
+      endif(${_prefix}_FOUND)
+    endforeach(_pkg_alt)
+
+    if (NOT ${_prefix}_FOUND)
+      if(${_pkg_is_required})
+        message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found")
+      endif(${_pkg_is_required})
+    endif(NOT ${_prefix}_FOUND)
+    
+    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+  endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})  
+endmacro(pkg_search_module)
+
+### 
+macro(PKGCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
+  message(STATUS "WARNING: you are using the obsolete 'PKGCONFIG' macro")
+  _pkg_check_modules_internal(0 0 _PKGCONFIG_TMP "${_package}")
+  if (_PKGCONFIG_TMP_FOUND)
+    set(${_include_DIR} ${_PKGCONFIG_TMP_INCLUDEDIR})
+    set(${_link_DIR}    ${_PKGCONFIG_TMP_LIBDIR})
+    set(${_link_FLAGS}  ${_PKGCONFIG_TMP_LDFLAGS})
+    set(${_cflags}      ${_PKGCONFIG_TMP_CFLAGS})
+    set(_return_VALUE 0)
+  else(_PKGCONFIG_TMP_FOUND)
+    set(${_include_DIR})
+    set(${_link_DIR})
+    set(${_link_FLAGS})
+    set(${_cflags})
+    set(_return_VALUE 1)
+  endif(_PKGCONFIG_TMP_FOUND)
+endmacro(PKGCONFIG)
+
+
+### Local Variables:
+### mode: cmake
+### End:
Index: /d-collide/tags/1.0.0/cmake/modules/MyInstallHeaders.cmake
===================================================================
--- /d-collide/tags/1.0.0/cmake/modules/MyInstallHeaders.cmake (revision 1890)
+++ /d-collide/tags/1.0.0/cmake/modules/MyInstallHeaders.cmake (revision 1890)
@@ -0,0 +1,26 @@
+# This file defines the macros
+# MY_INSTALL_HEADERS
+# MY_INSTALL_HEADERS_RECURSIVE
+#
+# Usage: MY_INSTALL_HEADERS(foobar) to install the directory foobar
+#        and all of its headers to include/foobar
+
+macro(MY_INSTALL_HEADERS_RECURSIVE subdir)
+    _MY_INSTALL_HEADERS(${subdir} ON)
+endmacro(MY_INSTALL_HEADERS_RECURSIVE subdir)
+
+macro(MY_INSTALL_HEADERS subdir)
+    _MY_INSTALL_HEADERS(${subdir} OFF)
+endmacro(MY_INSTALL_HEADERS subdir)
+
+
+#internal macro
+macro(_MY_INSTALL_HEADERS subdir recursive)
+    file(GLOB _files "${subdir}/*.h")
+    install(FILES ${_files} DESTINATION include/d-collide/${subdir})
+
+    if (${recursive})
+    endif (${recursive})
+endmacro(_MY_INSTALL_HEADERS)
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/cmake/modules/FindOGRE.cmake
===================================================================
--- /d-collide/tags/1.0.0/cmake/modules/FindOGRE.cmake (revision 2006)
+++ /d-collide/tags/1.0.0/cmake/modules/FindOGRE.cmake (revision 2006)
@@ -0,0 +1,153 @@
+# This module locates OGRE, OIS and CEGUI - the latter two are requirements of
+# d-collide to use OGRE (OGRE does not strictly depend on them, but we consider
+# it an OGRE dependency).
+#
+# This module defines the following variables:
+#  OGRE_FOUND   - true if the required packages were found in the correct
+#                 version, otherwise false (don't use OGRE then)
+#  OGRE_INCLUDE_DIRS - a list of include directories (to be used in
+#                      INCLUDE_DIRS()) that tells cmake where to find the
+#                      headers of the required packages.
+#  OGRE_LIBRARY_DIRS - a list of library directories (to be used in
+#                      LINK_DIRECTORIES()) that tells cmake where to find the
+#                      libraries of the required packages
+#  OGRE_LIBRARIES    - a list of libraries (to be used in
+#                      TARGET_LINK_LIBRARIES()) that includes the libraries of
+#                      the required packages.
+#  OGRE_CFLAGS       - the cflags required for OGRE
+#  OGRE_CFLAGS_OTHERS - the cflags required for OGRE, without the -I flags
+#  OGRE_PLUGIN_DIRECTORY - the directory where OGRE plugins should be loaded
+#                          from
+
+set(_requiredVersion "OGRE>=1.4.0" "OIS>=0.6.0" "CEGUI>=0.5.0")
+
+find_package(PkgConfig)
+
+set(_orig_pkgconfig_path $ENV{PKG_CONFIG_PATH})
+if (WIN32)
+    # AB: the OGRE SDK on Win32 sets the OGRE_HOME environment variable
+    # AB: note that lib/pkgconfig is NOT delivered by OGRE SDK, but is our own
+    #     d-collide extension, to make finding ogre easier
+    set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH};$ENV{OGRE_HOME}\\lib\\pkgconfig")
+endif (WIN32)
+pkg_check_modules(_OGRE ${_requiredVersion})
+
+# If OGRE==1.4.0 is installed only (i.e. < 1.4.1) we need GLX >= 1.3, 1.2 won't
+# work.
+# Warn about that.
+if (_OGRE_FOUND AND _OGRE_OGRE_VERSION STREQUAL "1.4.0")
+    message(STATUS "WARNING: OGRE claims to be at version 1.4.0. Make sure you
+       have GLX >= 1.3 installed, OGRE 1.4.0 won't work with GLX 1.2. If you
+       are sure that you have at least OGRE 1.4.1, you can ignore this warning
+       (OGRE 1.4.1 claims to be 1.4.0, too)")
+endif (_OGRE_FOUND AND _OGRE_OGRE_VERSION STREQUAL "1.4.0")
+
+if (_OGRE_FOUND AND PKG_CONFIG_EXECUTABLE)
+    # OGRE needs absolute paths to its plugins (apparently it can't figure out its
+    # own installation prefix).
+    # -> so we retrieve the "plugindir" here, so that we can use it later on
+    execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} OGRE --variable=plugindir
+        RESULT_VARIABLE _failed
+        OUTPUT_VARIABLE _output
+    )
+    if (_failed)
+        message(ERROR "Could not use pkg-config to retrieve the plugindir of OGRE. Should never happen, since pkg-config already found OGRE!")
+        set(OGRE_FOUND FALSE)
+        set(_OGRE_PLUGIN_DIRECTORY "")
+    else (_failed)
+        # remove the line ending from the output
+        string(REGEX REPLACE "[\r\n]" "" _output "${_output}")
+
+        set (_OGRE_PLUGIN_DIRECTORY ${_output})
+        set (OGRE_FOUND TRUE)
+    endif (_failed)
+
+    if (OGRE_FOUND)
+        if (WIN32)
+            set (_ogre_gui_renderer OgreGUIRenderer)
+        else (WIN32)
+            set (_ogre_gui_renderer CEGUIOgreRenderer )
+        endif (WIN32)
+
+        set (OGRE_PLUGIN_DIRECTORY ${_OGRE_PLUGIN_DIRECTORY} CACHE STRING "Ogre Plugin directory")
+        set(OGRE_LIBRARIES
+            ${_ogre_gui_renderer} ${_OGRE_LIBRARIES}
+            CACHE STRING "Ogre libraries to link against"
+        )
+        set(OGRE_INCLUDE_DIRS
+            ${_OGRE_INCLUDE_DIRS}
+            CACHE STRING "Ogre include directories"
+        )
+        set(OGRE_LIBRARY_DIRS
+            ${_OGRE_LIBRARY_DIRS}
+            CACHE STRING "Directories containing Ogre libraries"
+        )
+        set(OGRE_CFLAGS
+            ${_OGRE_CFLAGS}
+            CACHE STRING "Ogre CFLAGS"
+        )
+        set(OGRE_CFLAGS_OTHERS
+            ${_OGRE_CFLAGS_OTHER}
+            CACHE STRING "Ogre CFLAGS without -I flags"
+        )
+    endif (OGRE_FOUND)
+else (_OGRE_FOUND AND PKG_CONFIG_EXECUTABLE)
+    set(OGRE_FOUND FALSE)
+endif (_OGRE_FOUND AND PKG_CONFIG_EXECUTABLE)
+
+
+# DH: Mac OS X specific (find & setup OGRE framework)
+if (APPLE)
+    set(OIS_INCLUDE_DIR "/Developer/Ogre/Dependencies/include/OIS")
+    set(OIS_LIBRARY_DIR "/Developer/Ogre/Dependencies/lib"
+                        "/Developer/Ogre/Dependencies/lib/Release")
+    
+    cmake_find_frameworks(Ogre ${_requiredVersion})
+    cmake_find_frameworks(OgreCEGUIRenderer ${_requiredVersion})
+    cmake_find_frameworks(CEGUI ${_requiredVersion})
+    cmake_find_frameworks(Carbon)
+    
+    if (Ogre_FRAMEWORKS)
+        set(OGRE_FOUND TRUE)
+
+        foreach (dir ${Ogre_FRAMEWORKS})
+            set(Ogre_FRAMEWORK_INCLUDES ${Ogre_FRAMEWORK_INCLUDES} ${dir}/Headers)
+        endforeach (dir)
+
+        foreach (dir ${CEGUI_FRAMEWORKS})
+            set(CEGUI_FRAMEWORK_INCLUDES ${CEGUI_FRAMEWORK_INCLUDES} ${dir}/Headers
+                        ${dir}/Headers/elements ${dir}/Headers/falagard)
+        endforeach (dir)
+
+        set (OGRE_INCLUDE_DIRS
+            ${OGRE_INCLUDE_DIRS}
+            ${Ogre_FRAMEWORK_INCLUDES}
+            ${CEGUI_FRAMEWORK_INCLUDES}
+            ${OIS_INCLUDE_DIR}
+        )
+        set (OGRE_LIBRARY_DIRS
+            ${OGRE_LIBRARY_DIRS}
+            ${OIS_LIBRARY_DIR}
+            ${CEGUI_LIBRARY_DIRS}
+        )
+        
+        set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${Carbon_FRAMEWORKS}
+                        ${Ogre_FRAMEWORKS} ${OgreCEGUIRenderer_FRAMEWORKS}
+                        ${CEGUI_FRAMEWORKS} ois)
+    endif (Ogre_FRAMEWORKS)
+endif (APPLE)
+
+# resetting PKG_CONFIG_PATH
+set(ENV{PKG_CONFIG_PATH} ${_orig_pkgconfig_path})
+
+mark_as_advanced(
+    OGRE_INCLUDE_DIRS
+    OGRE_LIBRARY_DIRS
+    OGRE_LIBRARIES
+    OGRE_CFLAGS
+    OGRE_CFLAGS_OTHERS
+    OGRE_PLUGIN_DIRECTORY
+)
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallCMake.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallCMake.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallCMake.nsh (revision 2241)
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallCMake
+    
+    Var /GLOBAL CMAKE_MAJOR_VERSION
+    Var /GLOBAL CMAKE_MINOR_VERSION
+    Var /GLOBAL CMAKE_PATCH_VERSION
+    
+    
+    DetailPrint "Searching for CMake..."
+    
+    nsExec::ExecToStack /TIMEOUT=30000 '"cmake" "--version"'
+    pop $5
+    StrCmp $5 0 cmakeFound cmakeInstall
+    
+    cmakeFound:
+        DetailPrint "Validating CMake version..."
+        
+        pop $6
+        
+        ; strip trailing 'cmake version'
+        StrCpy $6 $6 "" 14
+        
+        ; is a patch version included in version string?
+        ${StrLoc} $7 $6 "-patch" ">"
+        StrCmp $7 "" cmakeVersion cmakePatchedVersion
+        
+        ; process patch version info -> $CMAKE_PATCH_VERSION         
+        cmakePatchedVersion:
+            ${StrStr} $8 $6 "patch"
+            StrCpy $8 $8 "" 6
+            StrCpy $CMAKE_PATCH_VERSION $8
+            
+            ; strip patch version info
+            StrCpy $6 $6 $7
+            
+        ; process major and minor version info
+        cmakeVersion:
+            ${Explode} $7 "." $6
+            
+            ; process major version info -> $CMAKE_MAJOR_VERSION
+            pop $8
+            StrCpy $CMAKE_MAJOR_VERSION $8
+            
+            ; process minor version info -> $CMAKE_MINOR_VERSION
+            ${If} $7 != 1
+                pop $8
+                StrCpy $CMAKE_MINOR_VERSION $8
+            ${Else}
+                StrCpy $CMAKE_MINOR_VERSION 0
+            ${EndIf}
+        
+        ; check if the detected version is new enough
+        ${If} $CMAKE_MAJOR_VERSION < 2
+            GoTo cmakeFoundWithBadVersion
+        ${ElseIf} $CMAKE_MAJOR_VERSION == 2
+            ${If} $CMAKE_MINOR_VERSION < 4
+                GoTo cmakeFoundWithBadVersion
+            ${ElseIf} $CMAKE_MINOR_VERSION == 4
+                ${If} $CMAKE_PATCH_VERSION < 6
+                    GoTo cmakeFoundWithBadVersion
+                ${EndIf}
+            ${EndIf}
+        ${EndIf}
+        
+        DetailPrint "CMake version $CMAKE_MAJOR_VERSION.$CMAKE_MINOR_VERSION-patch $CMAKE_PATCH_VERSION found!"
+        return
+        
+    cmakeFoundWithBadVersion:
+        DetailPrint "Updating CMake..."
+        GoTo cmakeInstall
+        
+    
+    ; download setup routine and install it
+    cmakeInstall:
+        DetailPrint "Downloading CMake setup..."
+        
+        NSISdl::Download /TIMEOUT=30000 "${URL_CMAKE}" "$PLUGINSDIR\cmake-setup.exe"
+        
+        Pop $2
+        StrCmp $2 "success" cmakeDownloadSucceeded 
+        StrCmp $2 "cancel" cmakeDownloadCanceled cmakeDownloadFailed
+        
+        cmakeDownloadSucceeded:
+            HideWindow
+            ExecWait "$PLUGINSDIR\cmake-setup.exe"
+            BringToFront
+            return
+        
+        cmakeDownloadCanceled:
+            MessageBox MB_OK \
+                        "Download of CMake canceled by user!$\nYou wont be able to configure the source when you don't have CMake installed.$\n$\nPlease download and install it manually from http://www.cmake.org."
+            return
+        
+        cmakeDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download CMake!$\nYou wont be able to configure the source when you don't have CMake installed.$\n$\nPlease download and install it manually from http://www.cmake.org or hit 'Retry' to try to download it again." \
+                       IDRETRY cmakeInstall
+            return
+
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallLib3ds.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallLib3ds.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallLib3ds.nsh (revision 2241)
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallLib3ds
+    
+    DetailPrint "Searching for lib3ds include..."
+    
+    StrCmp $ENV_INCLUDE "" lib3dsInstall
+    
+    ${locate::Open} "$ENV_INCLUDE" "/F=1 /D=1 /N=file.h /B=0" $0
+    StrCmp $0 0 lib3dsError
+    
+    ${locate::Find} $0 $1 $2 $3 $4 $5 $6
+    ${locate::Close} $0
+    
+    ; split of last folder
+    ${RIndexOf} $0 $2 "\"
+    StrLen $1 $2
+    IntOp $0 $1 - $0
+    IntOp $0 $0 + 1
+    
+    StrCpy $0 $2 "" $0
+    StrCpy $1 $3
+    
+    
+    ; search lib3ds shared library
+    DetailPrint "Searching for lib3ds shared library..."
+    
+    ReadEnvStr $9 'PATH'
+    ${StrReplace} $9 ';' '|' $9
+    
+    ${locate::Open} $9 "/F=1 /D=0 /N=lib3ds.dll /B=0" $2
+    StrCmp $2 0 lib3dsError
+    
+    ${locate::Find} $2 $3 $4 $5 $6 $7 $8
+    ${locate::Close} $2
+    
+    ${locate::Unload}
+    
+    
+    ; check if both includes and library are present
+    ${If} $0 == "lib3ds"
+        ${If} $1 == "file.h"
+            ${If} $5 == "lib3ds.dll"
+                GoTo lib3dsFound
+            ${EndIf}
+        ${EndIf}
+    ${EndIf}
+    
+    
+    lib3dsInstall:
+        ; download and install lib3ds files
+        DetailPrint "Downloading lib3ds files..."
+        
+        NSISdl::Download /TIMEOUT=30000 "${URL_LIB3DS}" "$PLUGINSDIR\lib3ds.zip"
+        
+        Pop $0
+        StrCmp $0 "success" lib3dsDownloadSucceeded 
+        StrCmp $0 "cancel" lib3dsDownloadCanceled lib3dsDownloadFailed
+        
+        lib3dsDownloadSucceeded:
+            DetailPrint "Installing lib3ds..."
+            
+            ZipDLL::extractall "$PLUGINSDIR\lib3ds.zip" "$PLUGINSDIR"
+            
+            !insertmacro MoveFile "$PLUGINSDIR\lib3ds\LICENSE" "$INSTDIR\LICENSE.lib3ds"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\bin\lib3ds.dll" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\bin\lib3ds_d.dll" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\lib\lib3ds.lib" "$INSTDIR\lib"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\lib\lib3ds_d.lib" "$INSTDIR\lib"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\lib\lib3ds.exp" "$INSTDIR\lib"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\lib\lib3ds_d.exp" "$INSTDIR\lib"
+            ${FileCopy} "$PLUGINSDIR\lib3ds\include\lib3ds" "$INSTDIR\include"
+            
+            return
+            
+        lib3dsDownloadCanceled:
+            MessageBox MB_OK \
+                       "Download of lib3ds canceled by user!$\nYou wont be able to compile nor to run the demo application without the lib3ds library.$\n$\nPlease download and install it manually from http://lib3ds.sourceforge.net/."
+            return
+            
+        lib3dsDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download lib3ds!$\nYou wont be able to compile nor to run the demo application without the lib3ds library.$\n$\nPlease download and install it manually from http://lib3ds.sourceforge.net/ or hit 'Retry' to try to download it again." \
+                       IDRETRY lib3dsInstall
+            return
+            
+    lib3dsFound:
+        DetailPrint "Found lib3ds..."
+        return
+        
+    lib3dsError:
+        ${locate::Unload}
+        DetailPrint "Error during search process..."
+        MessageBox MB_ICONEXCLAMATION|MB_YESNO \
+                   "An error occured during the search for a possibly installed version of the lib3ds library.$\n$\n Do you wish to install the lib3ds library?" \
+                   IDYES lib3dsInstall
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallCppunit.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallCppunit.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallCppunit.nsh (revision 2241)
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallCppunit
+    
+    DetailPrint "Searching for CppUnit includes..."
+    
+    StrCmp $ENV_INCLUDE "" cppunitInstall
+    
+    ${locate::Open} "$ENV_INCLUDE" "/F=1 /D=1 /N=TestSuite.h /B=0" $0
+    StrCmp $0 0 cppunitError
+    
+    ${locate::Find} $0 $1 $2 $3 $4 $5 $6
+    ${locate::Close} $0
+    
+    ; split of last folder
+    ${RIndexOf} $0 $2 "\"
+    StrLen $1 $2
+    IntOp $0 $1 - $0
+    IntOp $0 $0 + 1
+    
+    StrCpy $0 $2 "" $0
+    StrCpy $1 $3
+    
+    
+    ; search lib3ds shared library
+    DetailPrint "Searching for CppUnit shared library..."
+    
+    ReadEnvStr $9 'PATH'
+    ${StrReplace} $9 ';' '|' $9
+    
+    ${locate::Open} $9 "/F=1 /D=0 /N=cppunit.dll /B=0" $2
+    StrCmp $2 0 cppunitError
+    
+    ${locate::Find} $2 $3 $4 $5 $6 $7 $8
+    ${locate::Close} $2
+    
+    ${locate::Unload}
+    
+    
+    ; check if both includes and library are present
+    ${If} $0 == "cppunit"
+        ${If} $1 == "TestSuite.h"
+            ${If} $5 == "cppunit.dll"
+                GoTo cppunitFound
+            ${EndIf}
+        ${EndIf}
+    ${EndIf}
+    
+    
+    cppunitInstall:
+        ; download and install lib3ds files
+        DetailPrint "Downloading CppUnit files..."
+        
+        NSISdl::Download /TIMEOUT=30000 "$URL_CPPUNIT" "$PLUGINSDIR\cppunit.zip"
+        
+        Pop $0
+        StrCmp $0 "success" cppunitDownloadSucceeded 
+        StrCmp $0 "cancel" cppunitDownloadCanceled cppunitDownloadFailed
+        
+        cppunitDownloadSucceeded:
+            DetailPrint "Installing CppUnit..."
+            
+            ZipDLL::extractall "$PLUGINSDIR\cppunit.zip" "$PLUGINSDIR"
+            
+            !insertmacro MoveFile "$PLUGINSDIR\cppunit\LICENSE" "$INSTDIR\LICENSE.cppunit"
+            ${FileCopy} "$PLUGINSDIR\cppunit\bin\*.dll" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\cppunit\lib\*.lib" "$INSTDIR\lib"
+            ${FileCopy} "$PLUGINSDIR\cppunit\include\cppunit" "$INSTDIR\include"
+            
+            return
+            
+        cppunitDownloadCanceled:
+            MessageBox MB_OK \
+                        "Download of CppUnit canceled by user!$\nYou wont be able to compile the tests without the CppUnit library.$\n$\nPlease download and install it manually from http://cppunit.sourceforge.net."
+            return
+            
+        cppunitDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download CppUnit!$\nYou wont be able to compile the tests without the CppUnit library.$\n$\nPlease download and install it manually from http://cppunit.sourceforge.net or hit 'Retry' to try to download it again." \
+                       IDRETRY cppunitInstall
+            return
+        
+    cppunitFound:
+        DetailPrint "CppUnit found..."
+        return
+        
+    cppunitError:
+        ${locate::Unload}
+        DetailPrint "Error during search process..."
+        MessageBox MB_ICONEXCLAMATION|MB_YESNO \
+                   "An error occured during the search for a possibly installed version of the CppUnit library.$\n$\n Do you wish to install the CppUnit library?" \
+                   IDYES cppunitInstall
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallVCRedist.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallVCRedist.nsh (revision 2139)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallVCRedist.nsh (revision 2139)
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallVCRedist
+    
+    ${If} $MSVC_FOUND = 0
+        ClearErrors
+        ReadRegDword $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7299052b-02a4-4627-81f2-1818da5d550d}" "Version"
+
+        ; If VC redistributables aren't installed already do so
+        IfErrors vcredistInstall
+        return
+        
+        vcredistInstall:
+            ; Download and install VC redistributables
+            DetailPrint "Downloading VC redistrubutable installer..."
+            
+            NSISdl::Download /TIMEOUT=30000 "${URL_VC_REDIST}" "$PLUGINSDIR\vcredist_x86.exe"
+            Pop $0
+            StrCmp $0 "success" vcredistDownloadSucceeded
+            StrCmp $0 "cancel" vcredistDownloadCanceled vcredistDownloadFailed
+            
+            vcredistDownloadSucceeded:
+                DetailPrint "Installing VC redistributables..."
+                
+                ExecWait '"$PLUGINSDIR\vcredist_x86.exe" /q:a /c:"VCREDI~3.EXE /q:a /c:""msiexec /i vcredist.msi /qb!"" "'
+                IfErrors vcredistInstallationFailed
+                return
+            
+            vcredistDownloadCanceled:
+                MessageBox MB_OK \
+                           "Download of VC redistributable installer canceled by user!$\nYou wont be able to start the demo application without the VC redistributables.$\n$\nPlease download and install it manually from http://www.microsoft.com."
+                return
+            
+            vcredistDownloadFailed:
+                MessageBox MB_ICONEXCLAMATION|MB_OK \
+                           "Couldn't download the VC redistributable installer!$\nYou wont be able to start the demo application without the VC redistributables.$\n$\nPlease download and install it manually from http://www.microsoft.com."
+                return
+            
+            vcredistInstallationFailed:
+                MessageBox MB_ICONEXCLAMATION|MB_OK \
+                           "Couldn't install the VC redistributables!$\nYou wont be able to start the demo application without the VC redistributables.$\n$\nPlease download and install it manually from http://www.microsoft.com."
+                return
+            
+    ${EndIf}
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/Explode.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/Explode.nsh (revision 2097)
+++ /d-collide/tags/1.0.0/release/include/Explode.nsh (revision 2097)
@@ -0,0 +1,84 @@
+; Taken from: http://nsis.sourceforge.net/Explode
+
+!define Explode "!insertmacro Explode"
+ 
+!macro  Explode Length  Separator   String
+    Push    `${Separator}`
+    Push    `${String}`
+    Call    Explode
+    Pop     `${Length}`
+!macroend
+ 
+Function Explode
+
+    ; Initialize variables
+    Var /GLOBAL explString
+    Var /GLOBAL explSeparator
+    Var /GLOBAL explStrLen
+    Var /GLOBAL explSepLen
+    Var /GLOBAL explOffset
+    Var /GLOBAL explTmp
+    Var /GLOBAL explTmp2
+    Var /GLOBAL explTmp3
+    Var /GLOBAL explArrCount
+  
+    ; Get input from user
+    Pop $explString
+    Pop $explSeparator
+  
+    ; Calculates initial values
+    StrLen $explStrLen $explString
+    StrLen $explSepLen $explSeparator
+    StrCpy $explArrCount 1
+ 
+    ${If}   $explStrLen <= 1          ;   If we got a single character
+    ${OrIf} $explSepLen > $explStrLen ;   or separator is larger than the string,
+        Push    $explString             ;   then we return initial string with no change
+        Push    1                       ;   and set array's length to 1
+        Return
+    ${EndIf}
+  
+    ; Set offset to the last symbol of the string
+    StrCpy $explOffset $explStrLen
+    IntOp  $explOffset $explOffset - 1
+  
+    ; Clear temp string to exclude the possibility of appearance of occasional data
+    StrCpy $explTmp   ""
+    StrCpy $explTmp2  ""
+    StrCpy $explTmp3  ""
+ 
+    ; Loop until the offset becomes negative
+    ${Do}
+        ; If offset becomes negative, it is time to leave the function
+        ${IfThen} $explOffset == -1 ${|} ${ExitDo} ${|}
+    
+        ; Remove everything before and after the searched part ("TempStr")
+        StrCpy $explTmp $explString $explSepLen $explOffset
+ 
+        ${If} $explTmp == $explSeparator
+            ; Calculating offset to start copy from
+            IntOp   $explTmp2 $explOffset + $explSepLen ;   Offset equals to the current offset plus length of separator
+            StrCpy  $explTmp3 $explString "" $explTmp2
+        
+            Push    $explTmp3                           ;   Throwing array item to the stack
+            IntOp   $explArrCount $explArrCount + 1     ;   Increasing array's counter
+        
+            StrCpy  $explString $explString $explOffset 0   ;   Cutting all characters beginning with the separator entry
+            StrLen  $explStrLen $explString
+        ${EndIf}
+    
+        ${If} $explOffset = 0                       ;   If the beginning of the line met and there is no separator,
+                                                    ;   copying the rest of the string
+            ${If} $explSeparator == ""              ;   Fix for the empty separator
+                IntOp   $explArrCount   $explArrCount - 1
+            ${Else}
+                Push    $explString
+            ${EndIf}
+        ${EndIf}
+    
+        IntOp   $explOffset $explOffset - 1
+    ${Loop}
+ 
+    Push $explArrCount
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/StrStr.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/StrStr.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/StrStr.nsh (revision 2010)
@@ -0,0 +1,78 @@
+; Credits
+;     Version 2.x
+;         Diego Pedroso (deguix).
+;     Version 1.x
+;         mgentry
+;         Amir Szekely (kichik)
+;         Ximon Eighteen (sunjammer)
+;         Diego Pedroso (deguix)
+;
+; Taken from: http://nsis.sourceforge.net/StrStr
+
+!define StrStr "!insertmacro StrStr"
+ 
+!macro StrStr ResultVar String SubString
+    Push `${String}`
+    Push `${SubString}`
+    Call StrStr
+    Pop `${ResultVar}`
+!macroend
+ 
+Function StrStr
+    /*
+    After this point:
+    ------------------------------------------
+    $R0 = SubString (input)
+    $R1 = String (input)
+    $R2 = SubStringLen (temp)
+    $R3 = StrLen (temp)
+    $R4 = StartCharPos (temp)
+    $R5 = TempStr (temp)
+    */
+    
+    ; Get input from user
+    Exch $R0
+    Exch
+    Exch $R1
+    Push $R2
+    Push $R3
+    Push $R4
+    Push $R5
+ 
+    ; Get "String" and "SubString" length
+    StrLen $R2 $R0
+    StrLen $R3 $R1
+    ; Start "StartCharPos" counter
+    StrCpy $R4 0
+ 
+    ; Loop until "SubString" is found or "String" reaches its end
+    ${Do}
+        ; Remove everything before and after the searched part ("TempStr")
+        StrCpy $R5 $R1 $R2 $R4
+     
+        ; Compare "TempStr" with "SubString"
+        ${IfThen} $R5 == $R0 ${|} ${ExitDo} ${|}
+        ; If not "SubString", this could be "String"'s end
+        ${IfThen} $R4 >= $R3 ${|} ${ExitDo} ${|}
+        ; If not, continue the loop
+        IntOp $R4 $R4 + 1
+    ${Loop}
+ 
+    /*
+    After this point:
+    ------------------------------------------
+    $R0 = ResultVar (output)
+    */
+ 
+    ; Remove part before "SubString" on "String" (if there has one)
+    StrCpy $R0 $R1 `` $R4
+    
+    ; Return output to user
+    Pop $R5
+    Pop $R4
+    Pop $R3
+    Pop $R2
+    Pop $R1
+    Exch $R0
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/DetectCompatibleCompiler.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/DetectCompatibleCompiler.nsh (revision 2061)
+++ /d-collide/tags/1.0.0/release/include/DetectCompatibleCompiler.nsh (revision 2061)
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkMSVC
+    
+    Var /GLOBAL MSVC_FOUND
+    Var /GLOBAL MSVC_SP1_FOUND
+    
+    Push $0
+    Push $1
+    Push $2
+    
+    DetailPrint "Searching for Microsoft Visual C++ compiler..."
+    
+    StrCpy $MSVC_FOUND 0
+    StrCpy $MSVC_SP1_FOUND 0
+    
+    ReadEnvStr $0 'VCInstallDir'
+    IfErrors msvcNotFound
+    
+    ClearErrors
+    StrCmp $0 "" msvcNotFound msvcFileFound
+    
+    msvcFileFound:
+        ${GetFileVersion} "$0\bin\c1xx.dll" $1
+        IfErrors msvcNotFound
+        
+        ${Explode} $2 "." $1
+        ${If} $2 >= 1
+            Pop $MSVC_FOUND
+            ${If} $MSVC_FOUND = 14
+                ${If} $2 >= 2
+                    Pop $3
+                    ${If} $3 = 0
+                        ${If} $2 >= 3
+                            Pop $3
+                            ${If} $3 = 50727
+                                ${If} $2 >= 4
+                                    Pop $3
+                                    ${StrLoc} $4 $3 " (" ">"
+                                    
+                                    ${If} $4 != ""
+                                        StrCpy $3 $3 $4
+                                    ${EndIf}
+                                    
+                                    ${If} $3 = 42
+                                        GoTo msvcFound
+                                    ${ElseIf} $3 > 42
+                                        GoTo msvcSP1Found
+                                    ${EndIf}
+                                ${EndIf}
+                            ${ElseIf} $3 > 50727
+                                GoTo msvcSP1Found
+                            ${EndIf}
+                        ${EndIf}
+                    ${ElseIf} $3 > 0
+                        GoTo msvcSP1Found
+                    ${EndIf}
+                ${EndIf}
+            ${ElseIf} $MSVC_FOUND > 14
+                GoTo msvcSP1Found
+            ${EndIf}
+        ${EndIf}
+        
+        GoTo msvcNotFound
+        
+        
+    msvcSP1Found:
+        StrCpy $MSVC_SP1_FOUND 1
+    
+    msvcFound:
+        DetailPrint "Found supported version of the Microsoft Visual C++ compiler!"
+        GoTo msvcRestore
+        
+    msvcNotFound:
+        StrCpy $MSVC_FOUND 0
+        ClearErrors
+        DetailPrint "No supported version of the Microsoft Visual C++ compiler found..."
+
+    msvcRestore:
+        Exch $0
+        Exch $1
+        Exch $2
+    
+FunctionEnd
+
+Function checkICC
+    
+    Var /GLOBAL ICC_FOUND
+    
+    Push $0
+    Push $1
+    Push $2
+    Push $3
+    
+    DetailPrint "Searching for Intel C++ compiler..."
+    
+    StrCpy $0 0
+    StrCpy $1 0
+    StrCpy $2 0
+    StrCpy $3 0
+    
+    iccNextOne:
+        EnumRegKey $1 HKCU "Software\Intel\Compilers\C++" $0
+        StrCmp $1 "" iccCancel
+        IntOp $0 $0 + 1
+        
+        ReadRegDWORD $2 HKCU "Software\Intel\Compilers\C++\$1" "Major Version"
+        ReadRegDWORD $3 HKCU "Software\Intel\Compilers\C++\$1" "Minor Version"
+        IfErrors iccNextOne
+        
+        ${If} $2 >= 10
+            ${If} $3 >= 0
+                GoTo iccFound
+            ${Else}
+                GoTo iccNextOne
+            ${EndIf}
+        ${Else}
+            GoTo iccNextOne
+        ${EndIf}
+        
+    iccCancel:
+        StrCpy $ICC_FOUND 0
+        DetailPrint "No supported Intel C++ compiler found..."
+        Goto iccRestore
+        
+    iccFound:
+        StrCpy $ICC_FOUND $2
+        DetailPrint "Intel C++ compiler version $2.$3 found..."
+        
+    iccRestore:
+        Exch $0
+        Exch $1
+        Exch $2
+        Exch $3
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/StrReplace.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/StrReplace.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/StrReplace.nsh (revision 2010)
@@ -0,0 +1,53 @@
+; StrReplace
+; Replaces all ocurrences of a given needle within a haystack with another string
+; Written by dandaman32
+;
+; Taken from: http://nsis.sourceforge.net/StrRep
+
+!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK
+    Push "${HAYSTACK}"
+    Push "${NEEDLE}"
+    Push "${NEEDLE2}"
+    Call StrReplace
+    Pop "${OUT}"
+!macroend
+ 
+!define StrReplace '!insertmacro "_strReplaceConstructor"'
+
+Function StrReplace
+    Var /GLOBAL STR_REPLACE_VAR_0
+    Var /GLOBAL STR_REPLACE_VAR_1
+    Var /GLOBAL STR_REPLACE_VAR_2
+    Var /GLOBAL STR_REPLACE_VAR_3
+    Var /GLOBAL STR_REPLACE_VAR_4
+    Var /GLOBAL STR_REPLACE_VAR_5
+    Var /GLOBAL STR_REPLACE_VAR_6
+    Var /GLOBAL STR_REPLACE_VAR_7
+    Var /GLOBAL STR_REPLACE_VAR_8
+
+    Exch $STR_REPLACE_VAR_2
+    Exch 1
+    Exch $STR_REPLACE_VAR_1
+    Exch 2
+    Exch $STR_REPLACE_VAR_0
+        StrCpy $STR_REPLACE_VAR_3 -1
+        StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1
+        StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0
+        loop:
+            IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1
+            StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3
+            StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found
+            StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done
+            Goto loop
+        found:
+            StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3
+            IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4
+            StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 "" $STR_REPLACE_VAR_8
+            StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7
+            StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0
+            Goto loop
+        done:
+    Pop $STR_REPLACE_VAR_1 ; Prevent "invalid opcode" errors and keep the
+    Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called
+    Exch $STR_REPLACE_VAR_0
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallOgre.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallOgre.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallOgre.nsh (revision 2241)
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallOgre
+    
+    DetailPrint "Search for OgreSDK..."
+    
+    StrLen $1 $ENV_OGRE_HOME
+    IntCmp $1 0 ogreNotFound ogreNotFound ogreFound
+    
+    ogreNotFound:
+        DetailPrint "Downloading OgreSDK setup..."
+        
+        NSISdl::Download /TIMEOUT=30000 "$URL_OGRE" "$PLUGINSDIR\ogre-setup.exe"
+        
+        Pop $2
+        StrCmp $2 "success" orgeDownloadSucceeded 
+        StrCmp $2 "cancel" ogreDownloadCanceled orgeDownloadFailed
+        
+        orgeDownloadSucceeded:
+            HideWindow
+            ExecWait "$PLUGINSDIR\ogre-setup.exe"
+            BringToFront
+            
+            Push "%OGRE_HOME%\bin\release"
+            Call AddToPath
+            
+            return
+        
+        ogreDownloadCanceled:
+            MessageBox MB_OK \
+                       "Download of OgreSDK canceled by user!$\nYou wont be able to start the demo application without the OgreSDK.$\n$\nPlease download and install it manually from http://www.ogre3d.org."
+            return
+        
+        orgeDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download the OgreSDK!$\nYou wont be able to start the demo application without the OgreSDK.$\n$\nPlease download and install it manually from http://www.ogre3d.org or hit 'Retry' to try to download it again." \
+                       IDRETRY ogreNotFound
+            return
+    
+    ogreFound:
+        DetailPrint "OgreSDK found..."
+        
+        Push "%OGRE_HOME%\bin\release"
+        Call AddToPath
+        
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/MoveFile.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/MoveFile.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/MoveFile.nsh (revision 2010)
@@ -0,0 +1,82 @@
+;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+; MoveFile macro
+;
+; Author:  theblazingangel@aol.com (for the AutoPatcher project - www.autopatcher.com)
+; Created: June 2007  
+; Taken from: http://nsis.sourceforge.net/MoveFileFolder
+;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+;==================
+; Declarations
+;==================
+
+Var switch_overwrite        ; indicates overwrite behaviour
+
+
+;==================
+; MoveFile macro
+;==================
+
+!macro MoveFile sourceFile destinationFile
+
+    !define MOVEFILE_JUMP ${__LINE__}
+
+    ; Check source actually exists
+
+        IfFileExists "${sourceFile}" +3 0
+        SetErrors
+        goto done_${MOVEFILE_JUMP}
+
+    ; Add message to details-view/install-log
+
+        DetailPrint "Moving/renaming file: ${sourceFile} to ${destinationFile}"
+
+    ; If destination does not already exists simply move file
+
+        IfFileExists "${destinationFile}" +3 0
+        rename "${sourceFile}" "${destinationFile}"
+        goto done_${MOVEFILE_JUMP}
+
+    ; If overwriting without 'ifnewer' check
+
+        ${If} $switch_overwrite == 1
+        delete "${destinationFile}"
+        rename "${sourceFile}" "${destinationFile}"
+        delete "${sourceFile}"
+        goto done_${MOVEFILE_JUMP}
+        ${EndIf}
+
+    ; If destination already exists
+
+        Push $R0
+        Push $R1
+        Push $R2
+        push $R3
+
+        GetFileTime "${sourceFile}" $R0 $R1
+        GetFileTime "${destinationFile}" $R2 $R3
+
+        IntCmp $R0 $R2 0 older_${MOVEFILE_JUMP} newer_${MOVEFILE_JUMP}
+        IntCmp $R1 $R3 older_${MOVEFILE_JUMP} older_${MOVEFILE_JUMP} newer_${MOVEFILE_JUMP}
+
+        older_${MOVEFILE_JUMP}:
+        delete "${sourceFile}"
+        goto time_check_done_${MOVEFILE_JUMP}
+
+        newer_${MOVEFILE_JUMP}:
+        delete "${destinationFile}"
+        rename "${sourceFile}" "${destinationFile}"
+        delete "${sourceFile}" ;incase above failed!
+
+        time_check_done_${MOVEFILE_JUMP}:
+
+        Pop $R3
+        Pop $R2
+        Pop $R1
+        Pop $R0
+
+    done_${MOVEFILE_JUMP}:
+
+    !undef MOVEFILE_JUMP
+
+!macroend
Index: /d-collide/tags/1.0.0/release/include/StrLoc.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/StrLoc.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/StrLoc.nsh (revision 2010)
@@ -0,0 +1,77 @@
+; Author: Diego Pedroso (deguix)
+; Taken from: http://nsis.sourceforge.net/StrLoc
+
+!define StrLoc "!insertmacro StrLoc"
+ 
+!macro StrLoc ResultVar String SubString StartPoint
+    Push "${String}"
+    Push "${SubString}"
+    Push "${StartPoint}"
+    Call StrLoc
+    Pop "${ResultVar}"
+!macroend
+ 
+Function StrLoc
+    /*
+    After this point:
+    ------------------------------------------
+    $R0 = StartPoint (input)
+    $R1 = SubString (input)
+    $R2 = String (input)
+    $R3 = SubStringLen (temp)
+    $R4 = StrLen (temp)
+    $R5 = StartCharPos (temp)
+    $R6 = TempStr (temp)
+    */
+ 
+    ; Get input from user
+    Exch $R0
+    Exch
+    Exch $R1
+    Exch 2
+    Exch $R2
+    Push $R3
+    Push $R4
+    Push $R5
+    Push $R6
+ 
+    ; Get "String" and "SubString" length
+    StrLen $R3 $R1
+    StrLen $R4 $R2
+    ; Start "StartCharPos" counter
+    StrCpy $R5 0
+ 
+    ; Loop until "SubString" is found or "String" reaches its end
+    ${Do}
+        ; Remove everything before and after the searched part ("TempStr")
+        StrCpy $R6 $R2 $R3 $R5
+     
+        ; Compare "TempStr" with "SubString"
+        ${If} $R6 == $R1
+            ${If} $R0 == `<`
+                IntOp $R6 $R3 + $R5
+                IntOp $R0 $R4 - $R6
+            ${Else}
+                StrCpy $R0 $R5
+            ${EndIf}
+            ${ExitDo}
+        ${EndIf}
+        ; If not "SubString", this could be "String"'s end
+        ${If} $R5 >= $R4
+            StrCpy $R0 ``
+            ${ExitDo}
+        ${EndIf}
+        ; If not, continue the loop
+        IntOp $R5 $R5 + 1
+    ${Loop}
+ 
+    ; Return output to user
+    Pop $R6
+    Pop $R5
+    Pop $R4
+    Pop $R3
+    Pop $R2
+    Exch
+    Pop $R1
+    Exch $R0
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/DumpLog.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/DumpLog.nsh (revision 2096)
+++ /d-collide/tags/1.0.0/release/include/DumpLog.nsh (revision 2096)
@@ -0,0 +1,47 @@
+; Taken from: http://nsis.sourceforge.net/Dump_log_to_file
+
+!define LVM_GETITEMCOUNT 0x1004
+!define LVM_GETITEMTEXT 0x102D
+ 
+Function DumpLog
+    Exch $5
+    Push $0
+    Push $1
+    Push $2
+    Push $3
+    Push $4
+    Push $6
+ 
+    FindWindow $0 "#32770" "" $HWNDPARENT
+    GetDlgItem $0 $0 1016
+    StrCmp $0 0 exit
+    FileOpen $5 $5 "w"
+    StrCmp $5 "" exit
+        SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
+        System::Alloc ${NSIS_MAX_STRLEN}
+        Pop $3
+        StrCpy $2 0
+        System::Call "*(i, i, i, i, i, i, i, i, i) i \
+                     (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
+    loop:
+        StrCmp $2 $6 done
+        System::Call "User32::SendMessageA(i, i, i, i) i \
+                     ($0, ${LVM_GETITEMTEXT}, $2, r1)"
+        System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
+        FileWrite $5 "$4$\r$\n"
+        IntOp $2 $2 + 1
+        Goto loop
+    done:
+        FileClose $5
+        System::Free $1
+        System::Free $3
+    exit:
+        Pop $6
+        Pop $4
+        Pop $3
+        Pop $2
+        Pop $1
+        Pop $0
+        Exch $5
+        
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/AddToPath.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/AddToPath.nsh (revision 2246)
+++ /d-collide/tags/1.0.0/release/include/AddToPath.nsh (revision 2246)
@@ -0,0 +1,449 @@
+; Taken from: http://nsis.sourceforge.net/Path_Manipulation
+
+!ifndef _AddToPath_nsh
+!define _AddToPath_nsh
+ 
+!verbose 3
+!include "WinMessages.NSH"
+!verbose 4
+ 
+
+; AddToPath - Adds the given dir to the search path.
+;        Input - head of the stack
+;        Note - Win9x systems requires reboot
+ 
+Function AddToPath
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+ 
+  DetailPrint "Adding '$0' to PATH"
+ 
+  Call IsNT
+  Pop $1
+  ${If} $1 = 1
+    ReadRegStr $1 HKCU "Environment" "PATH"
+  ${Else}
+    ReadEnvStr $1 PATH
+  ${EndIf}
+  
+  Push "$1;"
+  Push "$0;"
+  Call LocalStrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  Push "$1;"
+  Push "$0\;"
+  Call LocalStrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  StrCpy $3 $0
+  Push "$1;"
+  Push "$3;"
+  Call LocalStrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  Push "$1;"
+  Push "$3\;"
+  Call LocalStrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  ${StrLoc} $2 $1 $0 ">"
+  ${If} $2 != ""
+    GoTo AddToPath_done
+  ${EndIf}
+  
+  Call IsNT
+  Pop $1
+  StrCmp $1 1 AddToPath_NT
+    ; Not on NT
+    StrCpy $1 $WINDIR 2
+    FileOpen $1 "$1\autoexec.bat" a
+    FileSeek $1 -1 END
+    FileReadByte $1 $2
+    IntCmp $2 26 0 +2 +2 # DOS EOF
+      FileSeek $1 -1 END # write over EOF
+    FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
+    FileClose $1
+    SetRebootFlag true
+    Goto AddToPath_done
+ 
+  AddToPath_NT:
+    ReadRegStr $1 HKCU "Environment" "PATH"
+    StrCmp $1 "" AddToPath_NTdoIt
+      Push $1
+      Call Trim
+      Pop $1
+      StrCpy $0 "$1;$0"
+    AddToPath_NTdoIt:
+      WriteRegExpandStr HKCU "Environment" "PATH" $0
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  AddToPath_done:
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+ 
+; RemoveFromPath - Remove a given dir from the path
+;     Input: head of the stack
+ 
+Function un.RemoveFromPath
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  Push $5
+  Push $6
+ 
+  IntFmt $6 "%c" 26 # DOS EOF
+ 
+  DetailPrint "Removing '$0' from PATH"
+ 
+  Call un.IsNT
+  Pop $1
+  StrCmp $1 1 unRemoveFromPath_NT
+    ; Not on NT
+    StrCpy $1 $WINDIR 2
+    FileOpen $1 "$1\autoexec.bat" r
+    GetTempFileName $4
+    FileOpen $2 $4 w
+    StrCpy $0 "SET PATH=%PATH%;$0"
+    Goto unRemoveFromPath_dosLoop
+ 
+    unRemoveFromPath_dosLoop:
+      FileRead $1 $3
+      StrCpy $5 $3 1 -1 # read last char
+      StrCmp $5 $6 0 +2 # if DOS EOF
+        StrCpy $3 $3 -1 # remove DOS EOF so we can compare
+      StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "" unRemoveFromPath_dosLoopEnd
+      FileWrite $2 $3
+      Goto unRemoveFromPath_dosLoop
+      unRemoveFromPath_dosLoopRemoveLine:
+        SetRebootFlag true
+        Goto unRemoveFromPath_dosLoop
+ 
+    unRemoveFromPath_dosLoopEnd:
+      FileClose $2
+      FileClose $1
+      StrCpy $1 $WINDIR 2
+      Delete "$1\autoexec.bat"
+      CopyFiles /SILENT $4 "$1\autoexec.bat"
+      Delete $4
+      Goto unRemoveFromPath_done
+ 
+  unRemoveFromPath_NT:
+    ReadRegStr $1 HKCU "Environment" "PATH"
+    StrCpy $5 $1 1 -1 # copy last char
+    StrCmp $5 ";" +2 # if last char != ;
+      StrCpy $1 "$1;" # append ;
+    Push $1
+    Push "$0;"
+    Call un.LocalStrStr ; Find `$0;` in $1
+    Pop $2 ; pos of our dir
+    StrCmp $2 "" unRemoveFromPath_done
+      ; else, it is in path
+      # $0 - path to add
+      # $1 - path var
+      StrLen $3 "$0;"
+      StrLen $4 $2
+      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
+      StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
+      StrCpy $3 $5$6
+ 
+      StrCpy $5 $3 1 -1 # copy last char
+      StrCmp $5 ";" 0 +2 # if last char == ;
+        StrCpy $3 $3 -1 # remove last char
+ 
+      WriteRegExpandStr HKCU "Environment" "PATH" $3
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  unRemoveFromPath_done:
+    Pop $6
+    Pop $5
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+ 
+ 
+ 
+; AddToEnvVar - Adds the given value to the given environment var
+;        Input - head of the stack $0 environement variable $1=value to add
+;        Note - Win9x systems requires reboot
+ 
+Function AddToEnvVar
+ 
+  Exch $1 ; $1 has environment variable value
+  Exch
+  Exch $0 ; $0 has environment variable name
+ 
+  DetailPrint "Adding '$1' to $0"
+  Push $2
+  Push $3
+  Push $4
+ 
+ 
+  ReadEnvStr $2 $0
+  Push "$2;"
+  Push "$1;"
+  Call LocalStrStr
+  Pop $3
+  StrCmp $3 "" "" AddToEnvVar_done
+ 
+  Push "$2;"
+  Push "$1\;"
+  Call LocalStrStr
+  Pop $3
+  StrCmp $3 "" "" AddToEnvVar_done
+  
+  ${StrLoc} $3 $2 $1 ">"
+  ${If} $3 != ""
+    GoTo AddToEnvVar_done
+  ${EndIf}
+ 
+  Call IsNT
+  Pop $2
+  StrCmp $2 1 AddToEnvVar_NT
+    ; Not on NT
+    StrCpy $2 $WINDIR 2
+    FileOpen $2 "$2\autoexec.bat" a
+    FileSeek $2 -1 END
+    FileReadByte $2 $3
+    IntCmp $3 26 0 +2 +2 # DOS EOF
+      FileSeek $2 -1 END # write over EOF
+    FileWrite $2 "$\r$\nSET $0=%$0%;$4$\r$\n"
+    FileClose $2
+    SetRebootFlag true
+    Goto AddToEnvVar_done
+ 
+  AddToEnvVar_NT:
+    ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" $0
+    StrCpy $3 $2 1 -1 # copy last char
+    StrCmp $3 ";" 0 +2 # if last char == ;
+      StrCpy $2 $2 -1 # remove last char
+    StrCmp $2 "" AddToEnvVar_NTdoIt
+      StrCpy $1 "$2;$1"
+    AddToEnvVar_NTdoIt:
+      WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" $0 $1
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  AddToEnvVar_done:
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $0
+    Pop $1
+ 
+FunctionEnd
+ 
+; RemoveFromEnvVar - Remove a given value from a environment var
+;     Input: head of the stack
+ 
+Function un.RemoveFromEnvVar
+ 
+  Exch $1 ; $1 has environment variable value
+  Exch
+  Exch $0 ; $0 has environment variable name
+ 
+  DetailPrint "Removing '$1' from $0"
+  Push $2
+  Push $3
+  Push $4
+  Push $5
+  Push $6
+  Push $7
+ 
+  IntFmt $7 "%c" 26 # DOS EOF
+ 
+  Call un.IsNT
+  Pop $2
+  StrCmp $2 1 unRemoveFromEnvVar_NT
+    ; Not on NT
+    StrCpy $2 $WINDIR 2
+    FileOpen $2 "$2\autoexec.bat" r
+    GetTempFileName $5
+    FileOpen $3 $5 w
+    GetFullPathName /SHORT $1 $1
+    StrCpy $1 "SET $0=%$0%;$1"
+    Goto unRemoveFromEnvVar_dosLoop
+ 
+    unRemoveFromEnvVar_dosLoop:
+      FileRead $2 $4
+      StrCpy $6 $4 1 -1 # read last char
+      StrCmp $6 $7 0 +2 # if DOS EOF
+        StrCpy $4 $4 -1 # remove DOS EOF so we can compare
+      StrCmp $4 "$1$\r$\n" unRemoveFromEnvVar_dosLoopRemoveLine
+      StrCmp $4 "$1$\n" unRemoveFromEnvVar_dosLoopRemoveLine
+      StrCmp $4 "$1" unRemoveFromEnvVar_dosLoopRemoveLine
+      StrCmp $4 "" unRemoveFromEnvVar_dosLoopEnd
+      FileWrite $3 $4
+      Goto unRemoveFromEnvVar_dosLoop
+      unRemoveFromEnvVar_dosLoopRemoveLine:
+        SetRebootFlag true
+        Goto unRemoveFromEnvVar_dosLoop
+ 
+    unRemoveFromEnvVar_dosLoopEnd:
+      FileClose $3
+      FileClose $2
+      StrCpy $2 $WINDIR 2
+      Delete "$2\autoexec.bat"
+      CopyFiles /SILENT $5 "$2\autoexec.bat"
+      Delete $5
+      Goto unRemoveFromEnvVar_done
+ 
+  unRemoveFromEnvVar_NT:
+    ReadRegStr $2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" $0
+    StrCpy $6 $2 1 -1 # copy last char
+    StrCmp $6 ";" +2 # if last char != ;
+      StrCpy $2 "$2;" # append ;
+    Push $2
+    Push "$1;"
+    Call un.LocalStrStr ; Find `$1;` in $2
+    Pop $3 ; pos of our dir
+    StrCmp $3 "" unRemoveFromEnvVar_done
+      ; else, it is in path
+      # $1 - path to add
+      # $2 - path var
+      StrLen $4 "$1;"
+      StrLen $5 $3
+      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove
+      StrCpy $7 $3 "" $4 # $7 is now the part after the path to remove
+      StrCpy $4 $6$7
+ 
+      StrCpy $6 $4 1 -1 # copy last char
+      StrCmp $6 ";" 0 +2 # if last char == ;
+      StrCpy $4 $4 -1 # remove last char
+ 
+      WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" $0 $4
+ 
+      ; delete reg value if null
+      StrCmp $4 "" 0 +2 # if null delete reg
+      DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" $0
+ 
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  unRemoveFromEnvVar_done:
+    Pop $7
+    Pop $6
+    Pop $5
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+ 
+ 
+ 
+ 
+!ifndef IsNT_KiCHiK
+!define IsNT_KiCHiK
+ 
+###########################################
+#            Utility Functions            #
+###########################################
+ 
+; IsNT
+; no input
+; output, top of the stack = 1 if NT or 0 if not
+;
+; Usage:
+;   Call IsNT
+;   Pop $R0
+;  ($R0 at this point is 1 or 0)
+ 
+!macro IsNT un
+Function ${un}IsNT
+  Push $0
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
+  StrCmp $0 "" 0 IsNT_yes
+  ; we are not NT.
+  Pop $0
+  Push 0
+  Return
+ 
+  IsNT_yes:
+    ; NT!!!
+    Pop $0
+    Push 1
+FunctionEnd
+!macroend
+!insertmacro IsNT ""
+!insertmacro IsNT "un."
+ 
+!endif ; IsNT_KiCHiK
+ 
+; LocalStrStr
+; input, top of stack = string to search for
+;        top of stack-1 = string to search in
+; output, top of stack (replaces with the portion of the string remaining)
+; modifies no other variables.
+;
+; Usage:
+;   Push "this is a long ass string"
+;   Push "ass"
+;   Call LocalStrStr
+;   Pop $R0
+;  ($R0 at this point is "ass string")
+ 
+!macro LocalStrStr un
+Function ${un}LocalStrStr
+Exch $R1 ; st=haystack,old$R1, $R1=needle
+  Exch    ; st=old$R1,haystack
+  Exch $R2 ; st=old$R1,old$R2, $R2=haystack
+  Push $R3
+  Push $R4
+  Push $R5
+  StrLen $R3 $R1
+  StrCpy $R4 0
+  ; $R1=needle
+  ; $R2=haystack
+  ; $R3=len(needle)
+  ; $R4=cnt
+  ; $R5=tmp
+  loop:
+    StrCpy $R5 $R2 $R3 $R4
+    StrCmp $R5 $R1 done
+    StrCmp $R5 "" done
+    IntOp $R4 $R4 + 1
+    Goto loop
+done:
+  StrCpy $R1 $R2 "" $R4
+  Pop $R5
+  Pop $R4
+  Pop $R3
+  Pop $R2
+  Exch $R1
+FunctionEnd
+!macroend
+!insertmacro LocalStrStr ""
+!insertmacro LocalStrStr "un."
+ 
+!endif ; _AddToPath_nsh
+ 
+Function Trim ; Added by Pelaca
+    Exch $R1
+    Push $R2
+Loop:
+    StrCpy $R2 "$R1" 1 -1
+    StrCmp "$R2" " " RTrim
+    StrCmp "$R2" "$\n" RTrim
+    StrCmp "$R2" "$\r" RTrim
+    StrCmp "$R2" ";" RTrim
+    GoTo Done
+RTrim:  
+    StrCpy $R1 "$R1" -1
+    Goto Loop
+Done:
+    Pop $R2
+    Exch $R1
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/RIndexOf.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/RIndexOf.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/RIndexOf.nsh (revision 2010)
@@ -0,0 +1,32 @@
+; Taken from: http://nsis.sourceforge.net/IndexOf_%26_RIndexOf:_Find_index_of_character_in_string
+
+!define RIndexOf "!insertmacro RIndexOf"
+
+!macro RIndexOf Var Str Char
+    Push "${Char}"
+    Push "${Str}"
+    Call RIndexOf
+    Pop "${Var}"
+!macroend
+
+Function RIndexOf
+    Exch $R0
+    Exch
+    Exch $R1
+    Push $R2
+    Push $R3
+ 
+    StrCpy $R3 $R0
+    StrCpy $R0 0
+    IntOp $R0 $R0 + 1
+    StrCpy $R2 $R3 1 -$R0
+    StrCmp $R2 "" +2
+    StrCmp $R2 $R1 +2 -3
+     
+    StrCpy $R0 -1
+     
+    Pop $R3
+    Pop $R2
+    Pop $R1
+    Exch $R0
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallPkgconfig.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallPkgconfig.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallPkgconfig.nsh (revision 2241)
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallPkgconfig
+
+    DetailPrint "Searching pkg-config..."
+    
+    nsExec::ExecToStack /TIMEOUT=30000 '"pkg-config" "--version"'
+    pop $5
+    StrCmp $5 0 pkgconfigFound pkgconfigInstall
+    
+    pkgconfigFound:
+        pop $5
+        DetailPrint "pkg-config version $5 found!"
+        return
+        
+    pkgconfigInstall:
+        ; download and install pkgconfig files
+        
+        DetailPrint "Downloading pkg-config files..."
+        
+        NSISdl::Download /TIMEOUT=30000 "${URL_PKGCONFIG}" "$PLUGINSDIR\pkgconfig.zip"
+        
+        Pop $0
+        StrCmp $0 "success" pkgconfigDownloadSucceeded
+        StrCmp $0 "cancel" pkgconfigDownloadCanceled pkgconfigDownloadFailed
+        
+        NSISdl::Download /TIMEOUT=30000 "${URL_PKGCONFIG_FILES}" "$PLUGINSDIR\pkgconfig-files.zip"
+        
+        Pop $0
+        StrCmp $0 "success" pkgconfigDownloadSucceeded
+        StrCmp $0 "cancel" pkgconfigDownloadCanceled pkgconfigDownloadFailed
+        
+        pkgconfigDownloadSucceeded:
+            DetailPrint "Installing pkg-config..."
+            
+            ZipDLL::extractall "$PLUGINSDIR\pkgconfig.zip" "$PLUGINSDIR"
+            ZipDLL::extractall "$PLUGINSDIR\pkgconfig-files.zip" "$PLUGINSDIR"
+            
+            !insertmacro MoveFile "$PLUGINSDIR\pkgconfig\LICENSE" "$INSTDIR\LICENSE.pkgconfig"
+            ${FileCopy} "$PLUGINSDIR\pkgconfig\bin\pkg-config.exe" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\pkgconfig\bin\intl.dll" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\pkgconfig\bin\iconv.dll" "$INSTDIR\bin"
+            ${FileCopy} "$PLUGINSDIR\pkgconfig\bin\libglib-2.0-0.dll" "$INSTDIR\bin"
+            
+            ReadEnvStr $1 "OGRE_HOME"
+            ${FileCopy} "$PLUGINSDIR\CEGUI.pc" "$1\lib\pkgconfig"
+            ${FileCopy} "$PLUGINSDIR\OGRE.pc" "$1\lib\pkgconfig"
+            ${FileCopy} "$PLUGINSDIR\OIS.pc" "$1\lib\pkgconfig"
+            
+            return
+            
+        pkgconfigDownloadCanceled:
+            MessageBox MB_OK \
+                        "Download of pkg-config canceled by user!$\nCMake want be able to find some dependencies without pkg-config, thus you want be able to compile the d-collide project.$\n$\nPlease download and install it manually from http://pkg-config.freedesktop.org."
+            return
+            
+        pkgconfigDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download pkg-config!$\nCMake want be able to find some dependencies without pkg-config, thus you want be able to compile the d-collide project.$\n$\nPlease download and install it manually from http://pkg-config.freedesktop.org or hit 'Retry' to try to download it again." \
+                       IDRETRY pkgconfigInstall
+            return
+        
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/ConfigureSystemEnvironement.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/ConfigureSystemEnvironement.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/ConfigureSystemEnvironement.nsh (revision 2241)
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function configureSystemEnvironement
+    ;Adds the D-Collide installation directory to the environement
+    
+    ;$INSTDIR/bin     -> PATH
+    ;$INSTDIR/lib     -> LIB
+    ;$INSTDIR/include -> INCLUDE
+    
+    DetailPrint "Setting environment variables..."
+    
+    Push "$INSTDIR\bin"
+    Call AddToPath
+    
+    Push "LIB"
+    Push "$INSTDIR\lib"
+    Call AddToEnvVar
+    
+    Push "INCLUDE"
+    Push "$INSTDIR\include"
+    Call AddToEnvVar
+
+FunctionEnd
+
+Function un.configureSystemEnvironement
+    ;Removes the D-Collide installation directory from the environement
+    
+    ;$INSTDIR/bin             -/--> PATH
+    ;%OGRE_HOME%\bin\release  -/--> PATH
+    ;$INSTDIR/lib             -/--> LIB
+    ;$INSTDIR/include         -/--> INCLUDE
+    
+    Push "$INSTDIR\bin"
+    Call un.RemoveFromPath
+    
+    Push "%OGRE_HOME%\bin\release"
+    Call un.RemoveFromPath
+    
+    Push "LIB"
+    Push "$INSTDIR\lib"
+    Call un.RemoveFromEnvVar
+    
+    Push "INCLUDE"
+    Push "$INSTDIR\include"
+    Call un.RemoveFromEnvVar
+
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/CheckAndInstallPthreads.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/CheckAndInstallPthreads.nsh (revision 2241)
+++ /d-collide/tags/1.0.0/release/include/CheckAndInstallPthreads.nsh (revision 2241)
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+Function checkAndInstallPthreads
+
+    DetailPrint "Searching for pthreads includes..."
+    
+    StrCmp $ENV_INCLUDE "" pthreadsInstall
+    
+    ${locate::Open} "$ENV_INCLUDE" "/F=1 /D=1 /N=pthread.h /B=0" $0
+    StrCmp $0 0 pthreadsError
+    
+    ${locate::Find} $0 $1 $2 $3 $4 $5 $6
+    ${locate::Close} $0
+    
+    ; split of last folder
+    ${RIndexOf} $0 $2 "\"
+    StrLen $1 $2
+    IntOp $0 $1 - $0
+    IntOp $0 $0 + 1
+    
+    StrCpy $0 $2 "" $0
+    StrCpy $1 $3
+    
+    
+    ; search lib3ds shared library
+    DetailPrint "Searching for pthreads shared library..."
+    
+    ReadEnvStr $9 'PATH'
+    ${StrReplace} $9 ';' '|' $9
+    
+    ${locate::Open} $9 "/F=1 /D=1 /N=pthreadVC2.dll /B=0" $2
+    StrCmp $2 0 pthreadsError
+    
+    ${locate::Find} $2 $3 $4 $5 $6 $7 $8
+    ${locate::Close} $2
+    
+    ${locate::Unload}
+    
+    
+    ; check if both includes and library are present
+    ${If} $1 == "pthread.h"
+        ${If} $5 == "pthreadVC2.dll"
+            GoTo pthreadsFound
+        ${EndIf}
+    ${EndIf}
+    
+    
+    pthreadsInstall:
+        ; download and install pthreads
+        CreateDirectory `$INSTDIR\include\pthreads`
+        
+        MetaDl::Download "${URL_PTHREADS}/include/pthread.h" "$INSTDIR\include\pthreads\pthread.h"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        MetaDl::Download "${URL_PTHREADS}/include/sched.h" "$INSTDIR\include\pthreads\sched.h"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        MetaDl::Download "${URL_PTHREADS}/include/semaphore.h" "$INSTDIR\include\pthreads\semaphore.h"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        MetaDl::Download "${URL_PTHREADS}/lib/pthreadVC2.dll" "$INSTDIR\bin\pthreadVC2.dll"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        MetaDl::Download "${URL_PTHREADS}/lib/pthreadVC2.lib" "$INSTDIR\lib\pthreadVC2.lib"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        MetaDl::Download "${URL_PTHREADS}/COPYING" "$INSTDIR\LICENSE.pthreads"
+        Pop $0
+        StrCmp $0 "success" +2
+        StrCmp $0 "cancel" pthreadsDownloadCanceled pthreadsDownloadFailed
+        
+        return
+        
+        
+        pthreadsDownloadCanceled:
+            MessageBox MB_OK \
+                       "Download of pthreads canceled by user!$\nYou wont be able to compile nor to use the d-collide library without the pthreads library.$\n$\nPlease download and install it manually from http://sourceware.org/pthreads-win32/."
+            return
+            
+        pthreadsDownloadFailed:
+            MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL \
+                       "Couldn't download pthreads!$\nYou wont be able to compile nor to use the d-collide library without the pthreads library.$\n$\nPlease download and install it manually from http://sourceware.org/pthreads-win32/ or hit 'Retry' to try to download it again." \
+                       IDRETRY pthreadsInstall
+            return
+    
+    pthreadsFound:
+        DetailPrint "Found pthreads..."
+        return
+        
+    pthreadsError:
+        ${locate::Unload}
+        DetailPrint "Error during search process..."
+        MessageBox MB_ICONEXCLAMATION|MB_YESNO \
+                   "An error occured during the search for a possibly installed version of the pthreads library.$\n$\n Do you wish to install the pthreads library?" \
+                   IDYES pthreadsInstall
+    
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/include/GetFileVersion.nsh
===================================================================
--- /d-collide/tags/1.0.0/release/include/GetFileVersion.nsh (revision 2010)
+++ /d-collide/tags/1.0.0/release/include/GetFileVersion.nsh (revision 2010)
@@ -0,0 +1,44 @@
+; Taken from: http://nsis.sourceforge.net/GetFileVersion
+
+Function GetFileVersion
+    !define GetFileVersion `!insertmacro GetFileVersionCall`
+ 
+    !macro GetFileVersionCall _FILE _RESULT
+        Push `${_FILE}`
+        Call GetFileVersion
+        Pop ${_RESULT}
+    !macroend
+ 
+    Exch $0
+    Push $1
+    Push $2
+    Push $3
+    Push $4
+    Push $5
+    Push $6
+    ClearErrors
+ 
+    GetDllVersion '$0' $1 $2
+    IfErrors error
+    IntOp $3 $1 >> 16
+    IntOp $3 $3 & 0x0000FFFF
+    IntOp $4 $1 & 0x0000FFFF
+    IntOp $5 $2 >> 16
+    IntOp $5 $5 & 0x0000FFFF
+    IntOp $6 $2 & 0x0000FFFF
+    StrCpy $0 '$3.$4.$5.$6'
+    goto end
+ 
+    error:
+        SetErrors
+        StrCpy $0 ''
+ 
+    end:
+        Pop $6
+        Pop $5
+        Pop $4
+        Pop $3
+        Pop $2
+        Pop $1
+        Exch $0
+FunctionEnd
Index: /d-collide/tags/1.0.0/release/d-collide.nsi
===================================================================
--- /d-collide/tags/1.0.0/release/d-collide.nsi (revision 2246)
+++ /d-collide/tags/1.0.0/release/d-collide.nsi (revision 2246)
@@ -0,0 +1,589 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+; Setup Build Files
+;-------------------------------------------------------------------------------
+
+    !ifndef DONT_BUILD_FILES
+        !ifdef UNIX_BUILD
+            !system 'test -d build && rm -rf build'
+            !system 'test -d files && rm -rf files'
+            !system 'mkdir build'
+            !system 'mkdir files'
+            !cd 'build'
+            !system 'cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../files ../..' = 0
+            !system 'make install' = 0
+            
+            !cd '..'
+            !system 'svn export "http://d-collide.ematia.de/svn/d-collide/trunk/d-collide" files/src'
+        !else
+            !system 'if exist build rmdir /S /Q build'
+            !system 'if exist files rmdir /S /Q files'
+            !system 'mkdir build'
+            !system 'mkdir files'
+            !cd 'build'
+            !system 'cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../files -G "NMake Makefiles" ../..' = 0
+            !system 'nmake install' = 0
+            
+            !cd '..'
+            !system 'svn export "http://d-collide.ematia.de/svn/d-collide/trunk/d-collide" files\src'
+        !endif
+    !endif
+
+
+; General
+;-------------------------------------------------------------------------------
+
+    ; Name and File
+    Name "D-Collide"
+    OutFile "dcollide-setup.exe"
+    
+    ; Default installation directory
+    InstallDir $PROGRAMFILES\D-Collide
+    
+    ; Get installation directory from registry if available
+    InstallDirRegKey HKCU \
+                     "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                     "InstallLocation"
+    
+    ; Removes annoying copyright notice
+    BrandingText " "
+    
+    ; For Vista compatibility
+    RequestExecutionLevel admin
+    
+    ; Set compression method for smaller installer executables
+    SetCompressor lzma
+
+
+; Defines / Settings
+;-------------------------------------------------------------------------------
+
+    !define MUI_ABORTWARNING
+
+
+; Includes
+;-------------------------------------------------------------------------------
+
+    !AddIncludeDir include
+    
+    !include "MUI.nsh"
+    !include "ZipDLL.nsh"
+    !include "Locate.nsh"
+    !include "LogicLib.nsh"
+    
+    !include "DumpLog.nsh"
+    !include "Explode.nsh"
+    !include "GetFileVersion.nsh"
+    !include "MoveFile.nsh"
+    !include "RIndexOf.nsh"
+    !include "StrLoc.nsh"
+    !include "StrReplace.nsh"
+    !include "StrStr.nsh"
+    !include "AddToPath.nsh"
+
+
+; Download locations
+;-------------------------------------------------------------------------------
+
+    !define URL_CMAKE           "http://www.cmake.org/files/v2.4/cmake-2.4.7-win32-x86.exe"
+    !define URL_CPPUNIT_VC8     "http://home.edo.uni-dortmund.de/~horst/dcollide/cppunit-msvc8.zip"
+    !define URL_CPPUNIT_VC8_SP1 "http://home.edo.uni-dortmund.de/~horst/dcollide/cppunit-msvc8-sp1.zip"
+    !define URL_LIB3DS          "http://home.edo.uni-dortmund.de/~horst/dcollide/lib3ds.zip"
+    !define URL_OGRE_VC71       "http://garr.dl.sourceforge.net/sourceforge/ogre/OgreSDKSetup1.4.5_VC71.exe"
+    !define URL_OGRE_VC8_SP1    "http://garr.dl.sourceforge.net/sourceforge/ogre/OgreSDKSetup1.4.5_VC80.exe"
+    !define URL_PTHREADS        "ftp://sourceware.org/pub/pthreads-win32/dll-latest"
+    !define URL_PKGCONFIG       "http://home.edo.uni-dortmund.de/~horst/dcollide/pkgconfig.zip"
+    !define URL_PKGCONFIG_FILES "http://home.edo.uni-dortmund.de/~horst/dcollide/pkgconfig-files.zip"
+    !define URL_VC_REDIST       "http://download.microsoft.com/download/e/1/c/e1c773de-73ba-494a-a5ba-f24906ecf088/vcredist_x86.exe"
+
+
+; Variables
+;-------------------------------------------------------------------------------
+
+    Var URL_OGRE
+    Var URL_CPPUNIT
+    
+    Var ENV_LIB
+    Var ENV_INCLUDE
+    Var ENV_OGRE_HOME
+    
+    Var STARTMENU_FOLDER_INSTALL
+    Var STARTMENU_FOLDER_UNINSTALL
+
+    
+; General Functions / Macros
+;-------------------------------------------------------------------------------
+
+    !define FileCopy `!insertmacro FileCopy`
+    
+    !macro FileCopy FilePath TargetDir
+        CreateDirectory `${TargetDir}`
+        CopyFiles /SILENT `${FilePath}` `${TargetDir}`
+    !macroend
+
+
+; Extended Installation Functions
+;-------------------------------------------------------------------------------
+
+    !include "DetectCompatibleCompiler.nsh"
+    !include "CheckAndInstallCMake.nsh"
+    !include "CheckAndInstallCppunit.nsh"
+    !include "CheckAndInstallLib3ds.nsh"
+    !include "CheckAndInstallOgre.nsh"
+    !include "CheckAndInstallPkgconfig.nsh"
+    !include "CheckAndInstallPthreads.nsh"
+    !include "CheckAndInstallVCRedist.nsh"
+    !include "ConfigureSystemEnvironement.nsh"
+
+
+; Pages
+;-------------------------------------------------------------------------------
+
+    !insertmacro MUI_PAGE_WELCOME
+    !insertmacro MUI_PAGE_COMPONENTS
+    !insertmacro MUI_PAGE_LICENSE "..\LICENSE.rtf"
+    !insertmacro MUI_PAGE_DIRECTORY
+    !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER_INSTALL
+    !insertmacro MUI_PAGE_INSTFILES
+    !insertmacro MUI_PAGE_FINISH
+
+    !insertmacro MUI_UNPAGE_WELCOME
+    !insertmacro MUI_UNPAGE_CONFIRM
+    !insertmacro MUI_UNPAGE_INSTFILES
+    !insertmacro MUI_UNPAGE_FINISH
+
+
+; Languages
+;-------------------------------------------------------------------------------
+
+    !insertmacro MUI_LANGUAGE "English"
+
+
+; Predefined Functions
+;-------------------------------------------------------------------------------
+
+    Function .onInit
+    
+        System::Call 'kernel32::CreateMutexA(i 0, i 0, t "d-collide.installer") i .r1 ?e'
+        Pop $R0
+        
+        StrCmp $R0 0 +3
+            MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running!"
+            Abort
+        
+        ReadRegStr $0 HKCU \
+                   "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                   "InstallLocation"
+        IfErrors +2 0
+        StrCpy $INSTDIR $0
+        
+        InitPluginsDir
+        
+        ReadEnvStr $ENV_OGRE_HOME 'OGRE_HOME'
+        ReadEnvStr $ENV_INCLUDE 'INCLUDE'
+        ReadEnvStr $ENV_LIB 'LIB'
+        
+        ${StrReplace} $ENV_LIB ';' '|' $ENV_LIB
+        ${StrReplace} $ENV_INCLUDE ';' '|' $ENV_INCLUDE
+        
+        StrCpy $switch_overwrite 0
+        
+        Call checkICC
+        Call checkMSVC
+        
+    FunctionEnd
+
+    Function un.onInit
+    
+        System::Call 'kernel32::CreateMutexA(i 0, i 0, t "d-collide.uninstaller") i .r1 ?e'
+        Pop $R0
+        
+        StrCmp $R0 0 +3
+            MessageBox MB_OK|MB_ICONEXCLAMATION "The uninstaller is already running!"
+            Abort
+        
+        ReadRegStr $0 HKCU \
+                   "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                   "InstallLocation"
+        IfErrors 0 +2
+        Abort
+        StrCpy $INSTDIR $0
+    
+    FunctionEnd
+
+    Function .onInstSuccess
+        MessageBox MB_YESNO "Congratulations, you've just successfully installed D-Collide!$\n$\nDo you want to view the README with useful information about bug reporting,$\ncompiling instructions and many more?" IDNO NoReadme
+            Exec '"notepad.exe" "$INSTDIR\README.txt"'
+        
+        NoReadme:
+    FunctionEnd
+
+
+; Installer Sections / Components
+;-------------------------------------------------------------------------------
+
+    InstType "full"
+    InstType "typical"
+    InstType "minimal"
+    
+    
+    Section "Library" "lib"
+        AddSize 13282
+        SectionIn RO
+        
+        ; Install files
+        SetOutPath $INSTDIR
+        File /oname=README.txt ..\README
+        File /oname=LICENSE.txt ..\LICENSE
+        
+        SetOutPath $INSTDIR\lib
+        File files\lib\dcollide.lib
+        
+        SetOutPath $INSTDIR\bin
+        File files\bin\dcollide.dll
+        
+        SetOutPath $INSTDIR\include
+        File /r files\include\*
+        
+        
+        ; Check Dependencies and install them if needed,
+        ; afterwards configure the system enviroment variables
+        Call checkAndInstallPthreads
+        Call checkAndInstallVCRedist
+        Call configureSystemEnvironement
+        
+        
+        ; Add our application to the 'Add/Remove Programs' panel 
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "DisplayName" "D-Collide - Collision Detection Library"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "UninstallString" "$INSTDIR\Uninstall.exe"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "InstallLocation" "$INSTDIR"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "DisplayIcon" "$INSTDIR\bin\d-collide.dll,0"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "Publisher" "PG 510, University of Dortmund"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "HelpLink" "http://d-collide.ematia.de"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "URLUpdateInfo" "http://d-collide.ematia.de"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "URLInfoAbout" "http://d-collide.ematia.de"
+        
+        WriteRegStr HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "DisplayVersion" "0.1.0 beta"                    
+        
+        WriteRegDWORD HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "VersionMajor" 0
+        
+        WriteRegDWORD HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "VersionMinor" 1
+        
+        WriteRegDWORD HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "NoModify" 1
+        
+        WriteRegDWORD HKCU \
+                    "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" \
+                    "NoRepair" 1
+        
+        
+        ; Create Unistaller
+        WriteUninstaller "$INSTDIR\Uninstall.exe"
+        
+        
+        ; Create start menu folder and uninstall shortcut
+        !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+            CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER_INSTALL"
+            CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER_INSTALL\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
+        !insertmacro MUI_STARTMENU_WRITE_END
+        
+        
+        ; Dump log to file
+        StrCpy $0 "$INSTDIR\install.log"
+        Push $0
+        Call DumpLog
+        
+    SectionEnd
+    
+    
+    Section /o "Demo Application" "demo"
+        AddSize 1085
+        SectionIn 1 2
+        
+        SetOutPath $INSTDIR\bin
+        File files\bin\testapp.exe
+        
+        SetOutPath $INSTDIR\resources
+        File /r files\resources\*
+
+        ${If} $MSVC_FOUND > 0
+            ${If} $MSVC_SP1_FOUND = 1
+                ; Install OgreSDK with support for VC 8 SP1
+                StrCpy $URL_OGRE "${URL_OGRE_VC8_SP1}"
+            ${Else}
+                ; Install OgreSDK with support for VC 8 without SP1
+                StrCpy $URL_OGRE "${URL_OGRE_VC71}"
+            ${EndIf}
+        ${Else}
+            ; Intel Compiler or no supported compiler installed
+            ; Install OgreSDK with support for VC 8 SP1
+            StrCpy $URL_OGRE "${URL_OGRE_VC8_SP1}"
+        ${EndIf}
+        
+        Call checkAndInstallOgre
+        Call checkAndInstallLib3ds
+        
+        ; Create shortcut to demo application
+        !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+            CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER_INSTALL\Demo Application.lnk" "$INSTDIR\bin\testapp.exe"
+        !insertmacro MUI_STARTMENU_WRITE_END
+    SectionEnd
+    
+    Section /o "Documentation" "doc"
+        AddSize 2980
+        SectionIn 1 2
+        
+        SetOutPath $INSTDIR\doc
+        File /r files\doc\*
+        
+        ; Create shortcut to documentation
+        !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+            CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER_INSTALL\Documentation.lnk" "$INSTDIR\doc\index.html"
+        !insertmacro MUI_STARTMENU_WRITE_END
+    SectionEnd
+    
+    SectionGroup /e "Developing Files" "dev"
+        Section /o "Source Code" src
+            AddSize 5492
+            SectionIn 1
+            
+            SetOutPath $INSTDIR\src
+            File /r files\src\*
+            
+        SectionEnd
+        
+        Section /o "Dependencies" "dep"
+            AddSize 0
+            SectionIn 1
+            
+            ${If} $ICC_FOUND = 0
+            ${OrIf} $MSVC_FOUND = 0
+                MessageBox MB_ICONEXCLAMATION|MB_OK "No supported compiler found.$\nPlease install either the Intel C++ Compiler (>= version 10) and/or the Microsoft Visual C++ Compiler (>= version 8 SP1).$\n$\nAll other dependencies will be autmatically detected and installed in the further processing of this setup!"
+                
+                StrCpy $URL_OGRE "${URL_OGRE_VC8_SP1}"
+                StrCpy $URL_CPPUNIT "${URL_CPPUNIT_VC8_SP1}"
+            ${Else}
+                ${If} $MSVC_FOUND > 0
+                    ${If} $MSVC_SP1_FOUND = 1
+                        ; Install dependencies with support for VC 8 SP1
+                        StrCpy $URL_OGRE "${URL_OGRE_VC8_SP1}"
+                        StrCpy $URL_CPPUNIT "${URL_CPPUNIT_VC8_SP1}"
+                    ${Else}
+                        ; Install dependencies with support for VC 8 without SP1
+                        StrCpy $URL_OGRE "${URL_OGRE_VC71}"
+                        StrCpy $URL_CPPUNIT "${URL_CPPUNIT_VC8}"
+                    ${EndIf}
+                ${Else}
+                    ; Install dependencies with support for VC 8 SP1
+                    StrCpy $URL_OGRE "${URL_OGRE_VC8_SP1}"
+                    StrCpy $URL_CPPUNIT "${URL_CPPUNIT_VC8_SP1}"
+                ${EndIf}
+            ${EndIf}
+            
+            SectionGetFlags "demo" $0
+            IntOp $0 $0 & ${SF_SELECTED}
+            
+            ${If} $0 != ${SF_SELECTED}
+                Call checkAndInstallLib3ds
+                Call checkAndInstallOgre
+            ${EndIf}
+            
+            Call checkAndInstallCMake
+            Call checkAndInstallCppunit
+            Call checkAndInstallPkgconfig
+            
+        SectionEnd
+    SectionGroupEnd
+    
+    
+    LangString DESC_LIB  ${LANG_ENGLISH} "The library"
+    LangString DESC_DEMO ${LANG_ENGLISH} "A demo application which demonstrates the functionallity of the library"
+    LangString DESC_DOC  ${LANG_ENGLISH} "Documentation for the library (including API-Reference)"
+    LangString DESC_DEV  ${LANG_ENGLISH} "All needed files if you want to contribute in developing d-collide"
+    LangString DESC_SRC  ${LANG_ENGLISH} "The Source Code"
+    LangString DESC_DEP  ${LANG_ENGLISH} "Needed dependencies to compile the library from source"
+
+    !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+        !insertmacro MUI_DESCRIPTION_TEXT ${lib}  $(DESC_LIB)
+        !insertmacro MUI_DESCRIPTION_TEXT ${demo} $(DESC_DEMO)
+        !insertmacro MUI_DESCRIPTION_TEXT ${doc}  $(DESC_DOC)
+        !insertmacro MUI_DESCRIPTION_TEXT ${dev}  $(DESC_DEV)
+        !insertmacro MUI_DESCRIPTION_TEXT ${src}  $(DESC_SRC)
+        !insertmacro MUI_DESCRIPTION_TEXT ${dep}  $(DESC_DEP)
+    !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+; Uninstaller Section
+;-------------------------------------------------------------------------------
+
+    Section "Uninstall"
+        
+        ; Delete installed files and directories
+        Delete "$INSTDIR\Uninstall.exe"
+        Delete "$INSTDIR\install.log"
+        
+        Delete "$INSTDIR\README.txt"
+        Delete "$INSTDIR\LICENSE.txt"
+        Delete "$INSTDIR\bin\testapp.exe"
+        Delete "$INSTDIR\lib\dcollide.lib"
+        
+        Delete /REBOOTOK "$INSTDIR\bin\dcollide.dll"
+        
+        RMDir /r "$INSTDIR\doc"
+        RMDir /r "$INSTDIR\src"
+        
+        RMDir /r "$INSTDIR\include\d-collide"
+        RMDir /r "$INSTDIR\include\pthreads"
+        RMDir /r "$INSTDIR\include\cppunit"
+        RMDir /r "$INSTDIR\include\lib3ds"
+        
+        RMDir /r "$INSTDIR\resources\cegui-skin"
+        RMDir /r "$INSTDIR\resources\models"
+        RMDir /r "$INSTDIR\resources\textures"
+        
+        
+        ; Remove CppUnit files
+        Delete "$INSTDIR\LICENSE.cppunit"
+        
+        Delete "$INSTDIR\lib\cppunit.lib"
+        Delete "$INSTDIR\lib\cppunitd.lib"
+        
+        Delete /REBOOTOK "$INSTDIR\bin\cppunit.dll"
+        Delete /REBOOTOK "$INSTDIR\bin\cppunitd.dll"
+        
+        ; Remove Lib3ds files
+        Delete "$INSTDIR\LICENSE.lib3ds"
+        
+        Delete "$INSTDIR\lib\lib3ds.lib"
+        Delete "$INSTDIR\lib\lib3ds_d.lib"
+        Delete "$INSTDIR\lib\lib3ds.exp"
+        Delete "$INSTDIR\lib\lib3ds_d.exp"
+        
+        Delete /REBOOTOK "$INSTDIR\bin\lib3ds.dll"
+        Delete /REBOOTOK "$INSTDIR\bin\lib3ds_d.dll"
+        
+        ; Remove PkgConfig files
+        Delete "$INSTDIR\LICENSE.pkgconfig"
+        
+        Delete "$INSTDIR\bin\pkg-config.exe"
+        
+        Delete /REBOOTOK "$INSTDIR\bin\intl.dll"
+        Delete /REBOOTOK "$INSTDIR\bin\iconv.dll"
+        Delete /REBOOTOK "$INSTDIR\bin\libglib-2.0-0.dll"
+        
+        ; Remove pThreads files
+        Delete "$INSTDIR\LICENSE.pthreads"
+        
+        Delete "$INSTDIR\lib\pthreadVC2.lib"
+        Delete /REBOOTOK "$INSTDIR\bin\pthreadVC2.dll"
+        
+        
+        ; Remove remaining empty directories
+        RMDir "$INSTDIR\bin"
+        RMDir "$INSTDIR\lib"
+        RMDir "$INSTDIR\include"
+        RMDir "$INSTDIR\resources"
+        RMDir "$INSTDIR"
+        
+        
+        ; Delete start menu entry and all empty parent directories
+        !insertmacro MUI_STARTMENU_GETFOLDER Application $STARTMENU_FOLDER_UNINSTALL
+        
+        Delete "$SMPROGRAMS\$STARTMENU_FOLDER_UNINSTALL\Uninstall.lnk"
+        Delete "$SMPROGRAMS\$STARTMENU_FOLDER_UNINSTALL\Demo Application.lnk"
+        Delete "$SMPROGRAMS\$STARTMENU_FOLDER_UNINSTALL\Documentation.lnk"
+        
+        StrCpy $STARTMENU_FOLDER_UNINSTALL "$SMPROGRAMS\$STARTMENU_FOLDER_UNINSTALL"
+        
+        startMenuDeleteLoop:
+            ClearErrors
+            RMDir $STARTMENU_FOLDER_UNINSTALL
+            GetFullPathName $STARTMENU_FOLDER_UNINSTALL "$STARTMENU_FOLDER_UNINSTALL\.."
+            
+            IfErrors +2
+            StrCmp $STARTMENU_FOLDER_UNINSTALL $SMPROGRAMS 0 startMenuDeleteLoop
+        
+        
+        ; Delete entry in the 'Add/Remove Programs' panel
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "DisplayName"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "UninstallString"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "InstallLocation"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "DisplayIcon"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "Publisher"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "HelpLink"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "URLUpdateInfo"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "URLInfoAbout"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "DisplayVersion"                    
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "VersionMajor"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "VersionMinor"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "NoModify"
+        DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide" "NoRepair"
+        
+        DeleteRegKey /ifempty HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\D-Collide"
+        
+        
+        ; Reset environement settings
+        Call un.configureSystemEnvironement
+        
+    SectionEnd
Index: /d-collide/tags/1.0.0/release/make_source_release.sh
===================================================================
--- /d-collide/tags/1.0.0/release/make_source_release.sh (revision 2285)
+++ /d-collide/tags/1.0.0/release/make_source_release.sh (revision 2285)
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# Simple script to make a d-collide source distribution.
+# Usage
+#   ./make_source_release <path_to_d-collide_sources> <release_name>
+
+
+SOURCE_DIRECTORY="$1"
+RELEASE_NAME="$2"
+
+NON_SVN_MODELS="bunny.ply"
+NON_SVN_MODELS="$NON_SVN_MODELS bunny_lower_res2.ply"
+NON_SVN_MODELS="$NON_SVN_MODELS bunny_lower_res3.ply"
+NON_SVN_MODELS="$NON_SVN_MODELS bunny_lower_res4.ply"
+
+
+# export name without .tar.gz
+EXPORT_DIRECTORY="d-collide-$RELEASE_NAME"
+
+EXPORT_ARCHIVE="$EXPORT_DIRECTORY".tar.gz
+
+function print_usage() {
+    echo "Usage: $0 <path_to_dcollide_sources>"
+}
+
+if [ ! -d "$SOURCE_DIRECTORY" ]; then
+    if [ -z "$SOURCE_DIRECTORY" ]; then
+        print_usage
+    else
+        echo "Source directory $SOURCE_DIRECTORY does not exist"
+    fi
+    exit 1
+fi
+
+if [ ! -d "$SOURCE_DIRECTORY/testapp" ]; then
+    echo "$SOURCE_DIRECTORY does not seem to contain d-collide sources"
+    exit 1
+fi
+
+if [ -d "$EXPORT_DIRECTORY" ]; then
+    echo "Export directory $EXPORT_DIRECTORY already exists!"
+    exit 1
+fi
+
+if [ -e "$EXPORT_ARCHIVE" ]; then
+    echo "$EXPORT_ARCHIVE already exists!"
+    exit 1
+fi
+
+svn export "$SOURCE_DIRECTORY" "$EXPORT_DIRECTORY" > /dev/null
+if [ "$?" != "0" ]; then
+    echo "svn export failed."
+    exit 1
+fi
+for model in $NON_SVN_MODELS; do
+    file_path="testapp/resources/models/$model"
+    if [ ! -r "$SOURCE_DIRECTORY/$file_path" ]; then
+        echo "non-svn model $model not found"
+        exit 1
+    fi
+    cp "$SOURCE_DIRECTORY/$file_path" "$EXPORT_DIRECTORY/$file_path" || exit 1
+done
+
+tar czf "$EXPORT_ARCHIVE" "$EXPORT_DIRECTORY"
+if [ "$?" != "0" ]; then
+    echo "tar czvf failed."
+    exit 1
+fi
+
+rm -rf "$EXPORT_DIRECTORY"
+
+echo "Distribution completed: $EXPORT_ARCHIVE"
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.h (revision 2988)
+++ /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.h (revision 2988)
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_OGRESCENEOBJECTFACTORY_H
+#define DCOLLIDE_OGRESCENEOBJECTFACTORY_H
+
+#include "dcollide-config_testapp.h" // fixes some compiler warnings caused by ogre
+#include <d-collide/math/vector.h>
+#include <OgreString.h>
+
+class MyObjectNode;
+
+namespace Ogre {
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+namespace dcollide {
+    class Proxy;
+    class Shape;
+    class BvhNode;
+    class BoundingVolume;
+    class Aabb;
+    class Obb;
+    class Kdop;
+    class BoundingSphere;
+    class HierarchicalGrid;
+}
+
+namespace ModelLoader {
+    class TextureInformation;
+}
+
+
+/*!
+ * \brief Creates OGRE objects from d-collide proxies
+ *
+ * This class is meant to take a (toplevel) d-collide proxy(-hierarchy) and
+ * generate an OGRE hierarchy from it consisting of \ref Ogre::SceneNode and
+ * some kind of \ref Ogre::MovableObject (e.g. \ref Ogre::ManualObject) objects.
+ *
+ */
+class OgreSceneObjectFactory {
+    public:
+        OgreSceneObjectFactory(Ogre::SceneManager* manager);
+        virtual ~OgreSceneObjectFactory();
+
+        Ogre::SceneNode* createSceneHierarchy(MyObjectNode* objectHierarchy);
+        Ogre::SceneNode* createBoundingVolumeSceneHierarchy(const dcollide::BvhNode* boundingVolumeNode);
+        Ogre::SceneNode* createHierarchicalGrid(
+                const dcollide::HierarchicalGrid* grid);
+
+        static void specifyBoundingVolumeLines(Ogre::ManualObject* object, const dcollide::BoundingVolume* bv);
+        static void specifyHierarchicalGrid(Ogre::ManualObject* object,
+                const dcollide::HierarchicalGrid* grid);
+        static void specifyTrianglesForShape(Ogre::ManualObject* object, const dcollide::Shape* shape, const ModelLoader::TextureInformation& textureInformation, bool useTextures = true);
+
+        static void initOgreObjectForBoundingVolume(Ogre::ManualObject* object, const dcollide::BoundingVolume* boundingVolume);
+
+    protected:
+        Ogre::String createUniqueObjectName(const dcollide::Shape* shape);
+        Ogre::String createUniqueObjectName(const dcollide::BoundingVolume* boundingVolume);
+        Ogre::ManualObject* createManualObject(const dcollide::Shape* shape, const ModelLoader::TextureInformation& textureInformation, bool useCulling = true, bool useTextures = true);
+        Ogre::ManualObject* createManualObject(const dcollide::BoundingVolume* boundingVolume);
+        static void initOgreObjectForAabb(Ogre::ManualObject* object, const dcollide::Aabb* bv);
+        static void initOgreObjectForKdop(Ogre::ManualObject* object, const dcollide::Kdop* bv);
+        static void initOgreObjectForSphere(Ogre::ManualObject* object, const dcollide::BoundingSphere* bv);
+        static void initOgreObjectForObb(Ogre::ManualObject* object, const
+                dcollide::Obb* obb);
+
+        static void specifyBoundingVolumeLinesForAabb(Ogre::ManualObject* object, const dcollide::Aabb* bv);
+        static void specifyBoundingVolumeLinesForObb(Ogre::ManualObject*
+                object, const dcollide::Obb* obb);
+        static void specifyBoundingVolumeLinesForKdop(Ogre::ManualObject* object, const dcollide::Kdop* bv);
+        static void specifyBoundingVolumeTrianglesForSphere(Ogre::ManualObject* object, const dcollide::BoundingSphere* bv);
+
+        static void specifyHierarchicalGridPoints(Ogre::ManualObject* object,
+                const dcollide::HierarchicalGrid* grid);
+
+    private:
+        Ogre::SceneManager* mOgreSceneManager;
+        static int mObjectNameNumber;
+};
+
+#endif // DCOLLIDE_OGRESCENEOBJECTFACTORY_H
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/ogrematerials.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/ogrematerials.cpp (revision 2470)
+++ /d-collide/tags/1.0.0/testapp/ogrematerials.cpp (revision 2470)
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "ogrematerials.h"
+
+#include <d-collide/debugstream.h>
+
+#include <modelloader/textureinformation.h>
+
+#include <OgreManualObject.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+#include <OgreString.h>
+#include <OgreMaterial.h>
+#include <OgreMaterialManager.h>
+#include <OgreBlendMode.h>
+
+
+OgreMaterials::OgreMaterials() {
+}
+
+OgreMaterials::~OgreMaterials() {
+}
+
+/*!
+ * Initialize the materials
+ *
+ * \return TRUE on success, FALSE otherwise (this object should not be used
+ * then).
+ */
+bool OgreMaterials::init() {
+    static bool initialized = false;
+    if (initialized) {
+        return true;
+    }
+    initialized = true;
+
+    Ogre::MaterialManager& materialManager = Ogre::MaterialManager::getSingleton();
+
+    // AB: we don't use the resourceGroup anyway, so it should not matter which
+    // one we pick.
+    const Ogre::String resourceGroup = "DCollideMaterials";
+    Ogre::MaterialPtr boundingVolumeMaterial = materialManager.create(getBoundingVolumeMaterial(), resourceGroup);
+    Ogre::MaterialPtr boundingVolumeMaterialCollisionBroad = materialManager.create(getBoundingVolumeMaterial(true, false), resourceGroup);
+    Ogre::MaterialPtr boundingVolumeMaterialCollisionMiddle = materialManager.create(getBoundingVolumeMaterial(false, true), resourceGroup);
+    Ogre::MaterialPtr hierarchicalGridMaterial =
+        materialManager.create(getHierarchicalGridMaterial(), resourceGroup);
+
+    // AB: some of these properties can be changed by using the corresponding
+    //     Ogre::Material methods. However these are just shortcuts to the ones in
+    //     Ogre::Pass and so for convenience (all properties at one place) we
+    //     always use the version in Ogre::Pass.
+
+    // no light => colour values are used (with light colour is usually ignored
+    // completely!)
+    // AB: atm we want light, so we don't use these lines
+    //boundingVolumeMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+
+    // if light is enabled: "colour tracking" means that the "colour" value at a
+    // vertex is used as "colour" of a light. use this for diffuse and ambient
+    // light and you get essentially a correctly coloured object.
+    // AB: atm we use one "global" colour for all objects of a certain type
+    //     (proxies or BVs), so no tracking is required.
+    //boundingVolumeMaterial->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_DIFFUSE | Ogre::TVC_AMBIENT);
+
+    boundingVolumeMaterial->getTechnique(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
+    boundingVolumeMaterial->getTechnique(0)->setDepthCheckEnabled(1);
+    boundingVolumeMaterial->getTechnique(0)->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
+    boundingVolumeMaterial->getTechnique(0)->setSelfIllumination(0.1, 0.3, 0.1);
+    boundingVolumeMaterial->getTechnique(0)->setShininess(0.3);
+    boundingVolumeMaterial->getTechnique(0)->setSpecular(0.2, 0.5, 0.2, 0.2);
+    boundingVolumeMaterial->getTechnique(0)->setShadingMode(Ogre::SO_FLAT);
+    boundingVolumeMaterial->getTechnique(0)->getPass(0)->setPolygonMode(Ogre::PM_SOLID);
+    boundingVolumeMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(0);
+    boundingVolumeMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.7, 0.0);
+    boundingVolumeMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.4, 0.0, 0.2);
+
+    //boundingVolumeMaterial->getTechnique(0)->getPass(0)->setPolygonMode(Ogre::PM_WIREFRAME);
+    //boundingVolumeMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 1.0, 0.0);
+    //boundingVolumeMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 1.0, 0.0, 1.0);
+
+    boundingVolumeMaterialCollisionBroad->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 1.0);
+    boundingVolumeMaterialCollisionBroad->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 1.0, 1.0);
+    boundingVolumeMaterialCollisionMiddle->getTechnique(0)->getPass(0)->setAmbient(0.0, 1.0, 1.0);
+    boundingVolumeMaterialCollisionMiddle->getTechnique(0)->getPass(0)->setDiffuse(0.0, 1.0, 1.0, 1.0);
+    hierarchicalGridMaterial->getTechnique(0)->getPass(0)->
+            setAmbient(1.0, 0.7, 0.0);
+    hierarchicalGridMaterial->getTechnique(0)->getPass(0)->
+            setDiffuse(1.0, 0.7, 0.0, 1.0);
+
+    boundingVolumeMaterialCollisionBroad->getTechnique(0)->getPass(0)->setPolygonMode(Ogre::PM_WIREFRAME);
+    boundingVolumeMaterialCollisionMiddle->getTechnique(0)->getPass(0)->setPolygonMode(Ogre::PM_WIREFRAME);
+    hierarchicalGridMaterial->getTechnique(0)->getPass(0)->
+            setPolygonMode(Ogre::PM_WIREFRAME);
+
+
+    Ogre::MaterialPtr collisionPointsMaterial = materialManager.create(getNarrowPhaseCollisionPointsMaterial(), resourceGroup);
+    collisionPointsMaterial->getTechnique(0)->getPass(0)->setAmbient(1.0, 1.0, 0.0);
+    collisionPointsMaterial->getTechnique(0)->getPass(0)->setDiffuse(1.0, 1.0, 0.0, 1.0);
+    collisionPointsMaterial->getTechnique(0)->getPass(0)->setPointSize(5.0);
+
+    Ogre::MaterialPtr normalsMaterial = materialManager.create(getNarrowPhaseNormalsMaterial(), resourceGroup);
+    normalsMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 1.0, 0.0);
+    normalsMaterial->getTechnique(0)->getPass(0)->setDiffuse(1.0, 1.0, 0.0, 1.0);
+
+
+    return true;
+}
+
+std::string OgreMaterials::getBoundingVolumeMaterial(bool collisionBroad, bool collisionMiddle) {
+    if (collisionBroad && collisionMiddle) {
+        std::cerr << dc_funcinfo << "invalid parameters" << std::endl;
+        return std::string();
+    }
+    if (!collisionBroad && !collisionMiddle) {
+        return "boundingvolume_material";
+    } else if (collisionBroad) {
+        return "boundingvolume_material_collision_broad";
+    } else if (collisionMiddle) {
+        return "boundingvolume_material_collision_middle";
+    }
+
+    return getBoundingVolumeMaterial(false, false); // fallback
+}
+
+std::string OgreMaterials::getNarrowPhaseCollisionPointsMaterial() {
+    return "narrowphase_collisionpoints_material";
+}
+
+std::string OgreMaterials::getNarrowPhaseNormalsMaterial() {
+    return "narrowphase_normals_material";
+}
+
+std::string OgreMaterials::getHierarchicalGridMaterial() {
+    return "hierarchicalGrid_material";
+}
+
+/*!
+ * Create a new \ref Ogre::Material for use in a \ref MyObjectNode which
+ * represents a \ref dcollide::Shape.
+ *
+ * The material is (curently anyway) valid for that single shape only and is
+ * meant to be destroyed on destruction of the corresponding \ref MyObjectNode.
+ */
+Ogre::MaterialPtr OgreMaterials::createShapeMaterial(const Ogre::String& name, const ModelLoader::TextureInformation& textureInformation, bool useCulling, bool useTextures) {
+    Ogre::MaterialManager& materialManager = Ogre::MaterialManager::getSingleton();
+    const Ogre::String resourceGroup = "DCollideMaterials";
+    Ogre::MaterialPtr material = materialManager.create(name, resourceGroup);
+
+    Ogre::Pass* pass = material->getTechnique(0)->getPass(0);
+
+    pass->setAmbient(1.0, 0.0, 0.0);
+
+    if (!useCulling) {
+        pass->setCullingMode(Ogre::CULL_NONE);
+    }
+
+    if (useTextures) {
+        if (textureInformation.isTextured()) {
+            pass->setAmbient(1.0, 1.0, 1.0);
+            pass->setDiffuse(1.0, 1.0, 1.0, 1.0);
+            pass->createTextureUnitState(textureInformation.getTextureFileName());
+        }
+    }
+
+    if (textureInformation.isTransparent()) {
+        material->getTechnique(0)->
+            setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
+    }
+
+    pass->setDiffuse(getShapeDiffuseColor(textureInformation));
+
+    return material;
+}
+
+Ogre::ColourValue OgreMaterials::getShapeDiffuseColor(const ModelLoader::TextureInformation& materialProperties, bool isPenetrating, bool isPenetrated) {
+    float alpha = 1.0;
+    if (materialProperties.isTransparent()) {
+        alpha = materialProperties.getTransparency();
+    }
+    if (!isPenetrating && !isPenetrated) {
+        if (materialProperties.isTextured()) {
+            return Ogre::ColourValue(1.0, 1.0, 1.0, alpha);
+        }
+    }
+    if (isPenetrating && isPenetrated) {
+        return Ogre::ColourValue(1.0, 0.0, 1.0, alpha);
+    }
+    if (isPenetrating) {
+        return Ogre::ColourValue(4.0, 4.5, 0.0, alpha);
+    }
+    if (isPenetrated) {
+        return Ogre::ColourValue(0.5, 1.0, 4.0, alpha);
+    }
+    return Ogre::ColourValue(1.0, 0.0, 0.0, alpha);
+}
+
+/*!
+ * Destroy (see \ref Ogre::MaterialManager::remove) a material created by \ref
+ * createShapeMaterial.
+ *
+ * If we ever want to re-use materials in multiple \ref MyObjectNode objects,
+ * this method should delete the material only if all \ref MyObjectNode objects
+ * using it have been deleted.
+ */
+void OgreMaterials::destroyShapeMaterial(const Ogre::String& name) {
+    Ogre::MaterialManager& materialManager = Ogre::MaterialManager::getSingleton();
+    materialManager.remove(name);
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/axisobject.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/axisobject.h (revision 1190)
+++ /d-collide/tags/1.0.0/testapp/axisobject.h (revision 1190)
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+// Code taken from http://www.ogre3d.org/wiki/index.php/ManualObject_AxisObject
+//
+//
+//  Filename : AxisObject.h
+
+#ifndef DCOLLIDE_AXIS_OBJECT_H
+#define DCOLLIDE_AXIS_OBJECT_H
+
+#include "dcollide-config_testapp.h" // fixes some compiler warnings caused by ogre
+#include <OgreString.h>
+#include <OgreBlendMode.h>
+
+namespace Ogre {
+    class ManualObject;
+    class SceneManager;
+}
+
+/*!
+ *\brief shows coordinate system directions
+ */
+class AxisObject {
+    enum BoxParts {
+        BOX_NONE    = 0x00,
+        BOX_TOP     = 0x01,
+        BOX_BOT     = 0x02,
+        BOX_FRONT   = 0x04,
+        BOX_BACK    = 0x08,
+        BOX_LEFT    = 0x10,
+        BOX_RIGHT   = 0x20,
+        BOX_ALL     = 0xFF
+    };
+    private:
+        void addMaterial(const Ogre::String& mat, Ogre::ColourValue &clr, Ogre::SceneBlendType sbt);
+        void addBox(Ogre::ManualObject* obj, Ogre::Vector3 dim, Ogre::Vector3 pos, Ogre::ColourValue color, short boxMask);
+
+    public:
+        Ogre::ManualObject*createAxis(Ogre::SceneManager* scene, const Ogre::String& name, Ogre::Real scale);
+};
+
+#endif //--_AXIS_OBJECT_H_
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/inputhandler.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/inputhandler.h (revision 2351)
+++ /d-collide/tags/1.0.0/testapp/inputhandler.h (revision 2351)
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_MYINPUTHANDLER_H
+#define DCOLLIDE_MYINPUTHANDLER_H
+
+#include <cstddef> // std::size_t
+#include <string>
+
+namespace Ogre {
+    class Camera;
+}
+
+class InputListener;
+class SceneBase;
+class UiActionCollection;
+class UiToggleAction;
+class TestApp;
+
+class InputHandler {
+    enum CameraSetup {
+        CAMERA_SETUP_VIEW_FRONT, //view from X-Axis to origin
+        CAMERA_SETUP_VIEW_SIDE, //view from Y-Axis to origin
+        CAMERA_SETUP_VIEW_TOP, //view from Z-Axis to origin
+        CAMERA_SETUP_VIEW_ISOMETRIC //view from 200, 200, 200 to origin
+    };
+
+    public:
+        InputHandler(std::size_t winHandle);
+        virtual ~InputHandler();
+
+        UiActionCollection* getActionCollection() const;
+        void initActions();
+
+        void setScene(SceneBase* scene);
+        void setCamera(Ogre::Camera* camera);
+        void setWindowSize(unsigned int width, unsigned int height);
+        void setTestApp(TestApp* testApp);
+
+        void showAllBoundingVolumes(bool);
+        void showAllProxies(bool);
+        void toggleShowAllBoundingVolumes();
+        void toggleShowAllProxies();
+        void toggleUseCollisionCaching();
+        void toggleShowHierarchicalGrid();
+        void setUseCollisionCache(bool);
+        void setShowHierarchicalGrid(bool);
+        void setShowNarrowPhaseResults(bool);
+        void queueQuit();
+        bool getWantQuit() const;
+        bool getPause() const;
+        bool getUseCollisionCache() const;
+        bool getUseThreads() const;
+        void changeCurrentScene(const std::string& sceneId);
+
+        void doSingleStep();
+        void setSingleStep(bool s);
+        bool getSingleStep() const;
+
+        void setCameraDefaultView(CameraSetup view);
+
+        void setChecked(const std::string& actionName, bool);
+        bool isChecked(const std::string& actionName) const;
+        void forceToggleCallbackActivation();
+
+        void captureInput(float timeSinceLastFrame);
+        void notifyWindowClosed();
+
+    private:
+        friend class InputListener;
+        InputListener* mInputListener;
+        Ogre::Camera* mCamera;
+        SceneBase* mScene;
+        TestApp* mTestApp;
+
+        bool mWantQuit;
+
+        bool mWantSingleStep;
+
+        UiActionCollection* mActionCollection;
+        UiToggleAction* mShowBoundingVolumesAction;
+        UiToggleAction* mShowProxiesAction;
+        UiToggleAction* mPauseAction;
+        UiToggleAction* mUseCollisionCacheAction;
+        UiToggleAction* mShowHierarchicalGridAction;
+        UiToggleAction* mUseThreads;
+};
+
+#endif
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/mydeformableobjectnode.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/mydeformableobjectnode.cpp (revision 3023)
+++ /d-collide/tags/1.0.0/testapp/mydeformableobjectnode.cpp (revision 3023)
@@ -0,0 +1,500 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "mydeformableobjectnode.h"
+
+#include "ogresceneobjectfactory.h"
+#include "ogrematerials.h"
+#include "odewrapper.h"
+
+#include <d-collide/dcollide-global.h>
+#include <d-collide/shapes/shape.h>
+#include <d-collide/shapes/mesh.h>
+#include <d-collide/shapes/mesh/vertex.h>
+#include <d-collide/shapes/mesh/triangle.h>
+#include <d-collide/math/vector.h>
+#include <d-collide/math/matrix.h>
+#include <d-collide/proxy.h>
+#include <d-collide/exceptions/exception.h>
+#include <d-collide/datatypes/multimapelement.h>
+
+#include <OgreSceneNode.h>
+#include <OgreManualObject.h>
+#include <OgreSceneManager.h>
+#include <OgreQuaternion.h>
+
+#include <algorithm>
+
+
+MyDeformableObjectNode::MyDeformableObjectNode(dcollide::World* world, dcollide::Shape* shape, int proxyType, bool useCulling, bool useTextures)
+    : MyObjectNode(world, shape, proxyType, useCulling, useTextures) {
+
+    if (!world) {
+        throw dcollide::NullPointerException("parameter world");
+    }
+    if ((shape != 0) && !(proxyType & dcollide::PROXYTYPE_DEFORMABLE)) {
+        throw dcollide::Exception("MyDeformableObjectNode can handle deformable proxies only!");
+    }
+
+    delete mODEGeom;
+    mODEGeom = 0;
+    mCenterPoint = 0;
+
+    mPrintDebugOutput = false;
+    mDebugOutputPrefix = "";
+}
+
+MyDeformableObjectNode::MyDeformableObjectNode(dcollide::Proxy* proxy, bool useCulling, bool useTextures)
+    : MyObjectNode(proxy, useCulling, useTextures) {
+
+    if (!proxy) {
+        throw dcollide::NullPointerException("parameter proxy");
+    }
+    if (    (proxy->getShape() != 0)
+        && !(proxy->getProxyType() & dcollide::PROXYTYPE_DEFORMABLE)) {
+
+        throw dcollide::Exception("MyDeformableObjectNode can handle deformable proxies only!");
+    }
+
+    delete mODEGeom;
+    mODEGeom = 0;
+    mCenterPoint = 0;
+    
+    mPrintDebugOutput = false;
+    mDebugOutputPrefix = "";
+}
+
+MyDeformableObjectNode::~MyDeformableObjectNode() {    
+    if (!mPhysicsObjects.empty()) {
+        if (mJoints) {
+            dJointGroupDestroy(mJoints);
+        }
+    }
+
+    if (!mCenterPoint) {
+        delete mCenterPoint;
+    }
+    
+    for(std::vector<MyODEDeformableTestAppGeom*>::iterator i = mPhysicsObjects.begin(); i != mPhysicsObjects.end(); ++i) {
+       delete (*i);
+    }
+}
+
+void MyDeformableObjectNode::createPhysicsBody(dWorldID odeWorld, dReal totalMass) {
+    if (!odeWorld) {
+        throw dcollide::NullPointerException("dWorldID odeWorld");
+    }
+
+    if (!mProxy->getShape()) {
+        std::cerr << "WARNING: cannot create physics body for a shapeless Proxy."<<std::endl;
+        return;
+    }
+
+    if (!mPhysicsObjects.empty()) {
+        std::cerr << "WARNING: previously created a physics body for this node." << std::endl;
+        return;
+    }
+
+    
+    const std::vector<dcollide::Vertex*> vertices
+        = mProxy->getShape()->getMesh()->getVertices();
+
+    int verticesCount = vertices.size();
+
+
+    // This object is physically equipped/enabled
+    mUseODE = true;
+
+    // Distribute the given mass to the whole body
+    dReal vertexRadius = 0.5;
+    dReal vertexMass = totalMass / verticesCount;
+
+    // Create a physics mid point for the object when its a volume object
+    dcollide::Vector3 meshCenter; 
+    if (mProxy->getProxyType() & dcollide::PROXYTYPE_CLOSEDHULL) {
+        mCenterPoint = new MyODETestAppGeom(this); 
+
+        mCenterPoint->setMoveNodeOnBodyMoved(false);
+
+        dMass* mass = new dMass();
+        dBodyID body = dBodyCreate(odeWorld);
+
+        dMassSetSphereTotal(mass, vertexMass, vertexRadius);
+
+        //dBodySetMass(body, mass);
+        dGeomSetBody((dGeomID)mCenterPoint, body);
+
+        meshCenter = mProxy->getShape()->getMesh()->getMidPoint();
+        dBodySetPosition(mCenterPoint->getBody(), meshCenter[0], meshCenter[1], meshCenter[2]);
+    }
+
+
+    // Create an physics body for each vertex of the mesh
+
+    mPhysicsObjects.reserve(verticesCount);
+    for (int index = 0; index < verticesCount; ++index) {
+
+        mPhysicsObjects.push_back(
+            new MyODEDeformableTestAppGeom(this, index)
+        );
+
+        dMass* mass = new dMass();
+        dBodyID body = dBodyCreate(odeWorld);
+
+        dMassSetSphereTotal(mass, vertexMass, vertexRadius);
+
+        //dBodySetMass(body, mass);
+        dGeomSetBody((dGeomID)mPhysicsObjects[index], body);
+
+
+        // Adjust the ODE body position
+        mPhysicsObjects[index]->setMoveNodeOnBodyMoved(false);
+
+        const dcollide::Vector3& position = vertices[index]->getWorldPosition();
+        dBodySetPosition(body, position[0], position[1], position[2]);
+
+        mPhysicsObjects[index]->setMoveNodeOnBodyMoved(true);
+    }
+
+
+    // Connect the created physics bodies through joints
+
+    // Create a joint groups (useful for static deformations)
+    mJoints = dJointGroupCreate(0);
+
+    // Set which avoids double creation
+    std::set<dcollide::MultiMapElement<dcollide::Vertex, dJointID> > finished;
+    std::set<dcollide::MultiMapElement<dcollide::Vertex, dJointID> >::iterator finished_pos;
+
+    // Create the actual joints
+    for (std::vector<dcollide::Vertex*>::const_iterator one = vertices.begin();
+         one != vertices.end();
+         ++one) {
+
+        dcollide::Vertex* v1 = (*one);
+
+        dBodyID body1 = mPhysicsObjects[v1->getVertexIndex()]->getBody();
+
+        //const dReal* v1Pos = dBodyGetPosition(body1);
+        //dcollide::debug() << "Body of vertex1 (worldPosition="<< v1->getWorldPosition()<<") is at (" << v1Pos[0] << ", " << v1Pos[1] << ", " << v1Pos[2] << ")";
+
+        const std::list<dcollide::Vertex*>& list = (*one)->getAdjacentVertices();
+        for (std::list<dcollide::Vertex*>::const_iterator two = list.begin();
+             two != list.end();
+             ++two) {
+
+            dcollide::Vertex* v2 = (*two);
+            dBodyID body2 = mPhysicsObjects[v2->getVertexIndex()]->getBody();
+
+            finished_pos = finished.find(dcollide::MultiMapElement<dcollide::Vertex, dJointID>(v1, v2));
+            
+            if (finished_pos == finished.end()) {
+                dcollide::Vector3 center  = (v1->getWorldPosition() + v2->getWorldPosition()) / 2;
+
+                dJointID joint = dJointCreateBall(odeWorld, mJoints);
+                //dJointID joint = dJointCreateFixed(odeWorld, mJoints);
+                //dJointID joint = dJointCreateUniversal(odeWorld, mJoints);
+
+                dJointAttach(joint, body1, body2);
+                dJointSetBallAnchor(joint, center.getX(), center.getY(), center.getZ());
+                //dJointSetFixed(joint);
+/*
+                dcollide::Vector3 axisOne  = (v1->getWorldPosition() - v2->getWorldPosition());
+                dcollide::Vector3 axisTwo  = v1->getAdjacentTriangles().front()->getWorldCoordinatesNormalVector();
+
+                dJointSetUniversalAnchor(joint, center.getX(), center.getY(), center.getZ());
+                dJointSetUniversalAxis1(joint, axisOne.getX(), axisOne.getY(), axisOne.getZ());
+                dJointSetUniversalAxis2(joint, axisTwo.getX(), axisTwo.getY(), axisTwo.getZ());
+*/
+                finished.insert(dcollide::MultiMapElement<dcollide::Vertex, dJointID>(v1, v2, joint));
+                
+/*
+                // Create the so called bending joints
+                std::list<dcollide::Vertex*>::const_iterator adjecent_pos;
+                const std::list<dcollide::Vertex*>& farneigbours = v2->getAdjacentVertices();
+                for (std::list<dcollide::Vertex*>::const_iterator neighbour = farneigbours.begin();
+                     neighbour != farneigbours.end();
+                     ++neighbour) {
+
+                    dcollide::Vertex* v3 = (*neighbour);
+
+                    adjecent_pos = find(list.begin(), list.end(), v3);
+                    if (adjecent_pos == list.end()) {
+                        // The current node is a far neighbour and thus should be connected
+
+                        finished_pos = finished.find(dcollide::MultiMapElement<dcollide::Vertex, dJointID>(v2, v3));
+            
+                        // If it wasn't previously created -> create it!
+                        if (finished_pos == finished.end()) {
+
+                            dcollide::Vector3 center  = (v2->getWorldPosition() + v3->getWorldPosition()) / 2;
+
+                            dJointID joint = dJointCreateBall(odeWorld, mJoints);
+
+                            dJointAttach(joint, body1, body2);
+                            dJointSetBallAnchor(joint, center.getX(), center.getY(), center.getZ());
+
+                            finished.insert(dcollide::MultiMapElement<dcollide::Vertex, dJointID>(v2, v3, joint));
+                        }
+                    }
+                }
+*/
+            }
+        }
+
+        // Connect all vertex "bodies" with the mid point
+        if (mCenterPoint != 0) {
+            dcollide::Vector3 center = (v1->getWorldPosition() + meshCenter) / 2;
+            dcollide::Vector3 direction = v1->getWorldPosition() - meshCenter;
+
+            dJointID joint = dJointCreateBall(odeWorld, mJoints);
+            //dJointID joint = dJointCreateSlider(odeWorld, mJoints);
+
+            dJointAttach(joint, body1, mCenterPoint->getBody());
+            //dJointSetFixed(joint);
+            
+            dJointSetBallAnchor(joint, center.getX(), center.getY(), center.getZ());
+            //dJointSetSliderAxis(joint, direction.getX(), direction.getY(), direction.getZ());
+        }
+    }
+}
+
+dBodyID MyDeformableObjectNode::getPhysicsBody(unsigned int vertexIndex) const {
+/*
+    bool empty = mPhysicsObjects.empty();
+    int size = mPhysicsObjects.size();
+
+    std::cout << std::endl
+        << "--- getPhysicsBody:" << std::endl
+        << " empty: " << empty << std::endl
+        << " vertexIndex: " << vertexIndex << std::endl
+        << "size: " << size << std::endl;
+*/
+    if (!mPhysicsObjects.empty() && (vertexIndex < mPhysicsObjects.size())) {
+/*
+        std::cout << " MyODEGeom: " << std::hex << (unsigned int) mPhysicsObjects[vertexIndex] << std::endl;
+        std::cout << " dGeomId: " << std::hex << (unsigned int) mPhysicsObjects[vertexIndex]->getBody() << std::endl;
+*/
+        return mPhysicsObjects[vertexIndex]->getBody();
+    }
+
+    return 0;
+}
+
+dGeomID MyDeformableObjectNode::getOdeGeom(unsigned int vertexIndex) const {
+
+    if (!mPhysicsObjects.empty() && (vertexIndex < mPhysicsObjects.size())) {
+        return (dGeomID) mPhysicsObjects[vertexIndex];
+    }
+
+    return 0;
+}
+
+void MyDeformableObjectNode::setVertexPosition(unsigned int vertexIndex, const dcollide::Vector3& vector, bool movePhysicsBody) {
+    /* Funktion die von jedem MyOdeDeformableGeom aufgerufen wird um die von
+     * ODE ÃŒbermittelte Transformation an das mesh weiter zu geben.
+     */
+    
+    if (mPrintDebugOutput) {
+        std::cout << "------ " << mDebugOutputPrefix << std::endl
+                  << "MyDeformableObjectNode::setVertexPosition" << std::endl
+                  << " - index : " << std::dec << vertexIndex
+                  << " - vector: " << vector << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    /*
+    dcollide::Matrix* matrix = new dcollide::Matrix();
+    if (mProxy->getTransformation().invert(matrix)) {
+        dcollide::Vector3* out = new dcollide::Vector3();
+        matrix->transform(out, vector);
+        mProxy->setVertexPosition(vertexIndex, vector);
+    }
+    */
+    
+    mProxy->setVertexPosition(vertexIndex, vector);
+
+    mBoundingVolumeDirty = true;
+
+    if (movePhysicsBody) {
+        updatePhysicsBodies(vertexIndex);
+    }
+}
+
+void MyDeformableObjectNode::translate(const dcollide::Vector3& translation, bool respectOrientation) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyDeformableObjectNode::translate(const dcollide::Vector3& translation)" << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->translate(translation, respectOrientation);
+
+    mBoundingVolumeDirty = true;
+    updatePhysicsBodies();
+}
+
+void MyDeformableObjectNode::setPosition(float x, float y, float z, bool movePhysicsBody) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "setPosition(x: " << x <<", y: " << y << ", z: " << z << ", movePhysicsBody: " << movePhysicsBody << ")" << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->setPosition(x, y, z);
+
+    mBoundingVolumeDirty = true;
+
+    if (movePhysicsBody) {
+        updatePhysicsBodies();
+    }
+}
+
+void MyDeformableObjectNode::rotate(const dcollide::Matrix& rotation, bool respectOrientation) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyDeformableObjectNode::rotate(const dcollide::Matrix& rotation)" << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->rotate(rotation, respectOrientation);
+
+    mBoundingVolumeDirty = true;
+    updatePhysicsBodies();
+}
+
+void MyDeformableObjectNode::setRotation(const dcollide::Matrix& rotation, bool movePhysicsBody) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyDeformableObjectNode::setRotation(const dcollide::Matrix& rotation, bool movePhysicsBody)" << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->setRotation(rotation);
+
+    mBoundingVolumeDirty = true;
+
+    if (movePhysicsBody) {
+        updatePhysicsBodies();
+    }
+}
+
+/*!
+ * \brief Performs an deformation on the deposited proxy
+ * 
+ * NOTICE: The size of given vector must match the Vertex count of the mesh
+ *         which should be deformed.  
+ */
+void MyDeformableObjectNode::deform(const std::vector<dcollide::Vector3>& vertexMoveArray) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyDeformableObjectNode::deform(const std::vector<dcollide::Vector3>& vertexMoveArray)" << std::endl;
+    }
+
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->deform(vertexMoveArray);
+
+    mBoundingVolumeDirty = true;
+}
+
+void MyDeformableObjectNode::updatePhysicsBodies(int vertexIndex) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyDeformableObjectNode::updatePhysicsBodies(vertexIndex: " << vertexIndex << ")" << std::endl;
+    }
+
+    if (!mPhysicsObjects.empty()) {
+
+        unsigned int index, objectCount;
+
+        dcollide::Vertex* vertex;
+        MyODEDeformableTestAppGeom* geom;
+
+
+        if (vertexIndex != -1) {
+            index = vertexIndex;
+            objectCount = vertexIndex+1;
+        } else {
+            index = 0;
+            objectCount = mPhysicsObjects.size();
+        }
+
+        const std::vector<dcollide::Vertex*>& vertices
+            = getProxy()->getShape()->getMesh()->getVertices();
+        for (/* nop */; index < objectCount; ++index) {
+
+            geom = mPhysicsObjects[index];
+            vertex = vertices[index];
+
+            dcollide::Vector3 bodyPosition = vertex->getWorldPosition();
+
+            if (mPrintDebugOutput) {
+                if (index == objectCount-1) {
+                    const dReal* odePosition = 0;
+                    odePosition = dBodyGetPosition(geom->getBody());
+
+                    std::cout << mDebugOutputPrefix << "----------" << std::endl;
+                    std::cout << mDebugOutputPrefix << "ODE Position (before move): " << odePosition[0] << ", " << odePosition[1] << ", " << odePosition[2] << std::endl;
+                    std::cout << mDebugOutputPrefix << "D-Collide World Position: " << bodyPosition << std::endl << std::endl;
+                }
+            }
+
+            geom->setMoveNodeOnBodyMoved(false);
+            dBodySetPosition(geom->getBody(),  bodyPosition.getX(),
+                                               bodyPosition.getY(),
+                                               bodyPosition.getZ());
+            geom->setMoveNodeOnBodyMoved(true);
+
+            if (mPrintDebugOutput) {
+                if (index == objectCount-1) {
+                    const dReal* odePosition = 0;
+                    odePosition = dBodyGetPosition(geom->getBody());
+                    std::cout << mDebugOutputPrefix << "ODE Position (after move): " << odePosition[0] << ", " << odePosition[1] << ", " << odePosition[2] << std::endl << std::endl;
+                }
+            }
+        }
+    }
+}
+
Index: /d-collide/tags/1.0.0/testapp/inputlistener.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/inputlistener.cpp (revision 2610)
+++ /d-collide/tags/1.0.0/testapp/inputlistener.cpp (revision 2610)
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "inputlistener.h"
+#include "inputhandler.h"
+#include "uiaction.h"
+#include "dcollide-config_testapp.h"
+#include "scenes/scenebase.h"
+
+#include <OgreVector3.h>
+#include <OgreCamera.h>
+
+#include <CEGUI/CEGUISystem.h>
+
+#define DCOLLIDE_NO_X11_GRAB
+
+CEGUI::MouseButton convertOisMouseButtonToCegui(int buttonId) {
+    switch (buttonId) {
+        case 0: return CEGUI::LeftButton;
+        case 1: return CEGUI::RightButton;
+        case 2: return CEGUI::MiddleButton;
+        case 3: return CEGUI::X1Button;
+        default: return CEGUI::LeftButton;
+    }
+}
+
+
+InputListener::InputListener(std::size_t winHandle, InputHandler* handler) {
+    mInputHandler = handler;
+    mMouseLook = false;
+
+    OIS::ParamList params;
+    std::ostringstream win;
+    win << winHandle;
+    params.insert(std::make_pair(std::string("WINDOW"), win.str()));
+
+    // for debugging (gdb)
+#ifdef DCOLLIDE_NO_X11_GRAB
+    params.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
+    params.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
+    params.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
+#endif
+    mInputManager = OIS::InputManager::createInputSystem(params);
+
+    // mMouseObject = static_cast<OIS::Mouse*>(mInputManager->createInputObject(OIS::OISMouse, false));
+    mMouseObject = static_cast<OIS::Mouse*>(mInputManager->createInputObject(OIS::OISMouse, true));
+    mKeyboardObject = static_cast<OIS::Keyboard*>(mInputManager->createInputObject(OIS::OISKeyboard, true));
+
+    mMouseObject->setEventCallback(this);
+    mKeyboardObject->setEventCallback(this);
+}
+
+InputListener::~InputListener() {
+    delete mMouseObject;
+    delete mKeyboardObject;
+    OIS::InputManager::destroyInputSystem(mInputManager);
+}
+
+void InputListener::setWindowSize(unsigned int width, unsigned int height) {
+    if (mMouseObject) {
+        const OIS::MouseState &state = mMouseObject->getMouseState();
+        // AB: OIS::MouseState::width and height are declared mutable, so we can
+        //     (and must) change it even in a const reference.
+        //
+        //     don't ever ask me what I think about this style.
+        state.width = width;
+        state.height = height;
+    }
+}
+
+/*!
+ * Called once per frame - triggers OIS to update the input device states.
+ */
+void InputListener::captureInput(float timeSinceLastFrame) {
+    mMouseObject->capture();
+    mKeyboardObject->capture();
+
+    if (!mInputHandler->mCamera) {
+        return;
+    }
+
+    const float moveBy = 150.0f * timeSinceLastFrame;
+    Ogre::Vector3 moveVector(0, 0, 0);
+    float rotationX = 0.0f;
+    float rotationY = 0.0f;
+    if (mKeyboardObject->isKeyDown(OIS::KC_UP)) {
+        moveVector += Ogre::Vector3(0.0f, 0.0f, -moveBy);
+    }
+    if (mKeyboardObject->isKeyDown(OIS::KC_DOWN)) {
+        moveVector += Ogre::Vector3(0.0f, 0.0f, moveBy);
+    }
+    if (mKeyboardObject->isKeyDown(OIS::KC_PGUP)) {
+        moveVector += Ogre::Vector3(0.0f, moveBy, 0.0f);
+    }
+    if (mKeyboardObject->isKeyDown(OIS::KC_PGDOWN)) {
+        moveVector += Ogre::Vector3(0.0f, -moveBy, 0.0f);
+    }
+    if (mKeyboardObject->isKeyDown(OIS::KC_LEFT)) {
+        moveVector += Ogre::Vector3(-moveBy, 0.0f, 0.0f);
+    }
+    if (mKeyboardObject->isKeyDown(OIS::KC_RIGHT)) {
+        moveVector += Ogre::Vector3(moveBy, 0.0f, 0.0f);
+    }
+
+    if (mMouseLook) {
+        const static float rotateAmount = 0.1f;
+        const OIS::MouseState& state = mMouseObject->getMouseState();
+        
+        if (state.X.rel != 0) {
+            rotationY += -state.X.rel * rotateAmount;
+        }
+        if (state.Y.rel != 0) {
+            rotationX += -state.Y.rel * rotateAmount;
+        }
+        
+        mInputHandler->mCamera->pitch(Ogre::Degree(rotationX));
+        mInputHandler->mCamera->yaw(Ogre::Degree(rotationY));
+    }
+
+    mInputHandler->mCamera->moveRelative(moveVector);
+}
+
+bool InputListener::keyPressed(const OIS::KeyEvent& event) {
+    if (event.key == OIS::KC_1) {
+        mInputHandler->setCameraDefaultView(InputHandler::CAMERA_SETUP_VIEW_FRONT);
+    } else if (event.key == OIS::KC_2) {
+        mInputHandler->setCameraDefaultView(InputHandler::CAMERA_SETUP_VIEW_SIDE);
+    } else if (event.key == OIS::KC_3) {
+        mInputHandler->setCameraDefaultView(InputHandler::CAMERA_SETUP_VIEW_TOP);
+    } else if (event.key == OIS::KC_4) {
+        mInputHandler->setCameraDefaultView(InputHandler::CAMERA_SETUP_VIEW_ISOMETRIC);
+    } else if (event.key == OIS::KC_R) {
+        mInputHandler->mScene->restart();
+    } else if (event.key == OIS::KC_SPACE) {
+        mInputHandler->mScene->action();
+    }
+    
+    if (mKeyboardObject->isKeyDown(OIS::KC_PERIOD)) {
+        //emulate stepping button
+    	mInputHandler->doSingleStep();
+    }
+    return true;
+}
+
+bool InputListener::keyReleased(const OIS::KeyEvent& event) {
+    if (event.key == OIS::KC_ESCAPE || event.key == OIS::KC_Q) {
+        mInputHandler->queueQuit();
+    }
+    if (mInputHandler && mInputHandler->getActionCollection()) {
+        mInputHandler->getActionCollection()->activateShortcut(event.key);
+    }
+    return true;
+}
+
+bool InputListener::mouseMoved(const OIS::MouseEvent& event) {
+    CEGUI::System::getSingleton().injectMouseMove(event.state.X.rel,
+                                                  event.state.Y.rel);
+    CEGUI::System::getSingleton().injectMouseWheelChange(event.state.Z.rel); 
+    return true;
+}
+
+bool InputListener::mousePressed(const OIS::MouseEvent&, OIS::MouseButtonID id) {
+    if (id == OIS::MB_Right) {
+        mMouseLook = true;
+    }
+    CEGUI::System::getSingleton().injectMouseButtonDown(convertOisMouseButtonToCegui(id));
+    return true;
+}
+
+bool InputListener::mouseReleased(const OIS::MouseEvent&, OIS::MouseButtonID id) {
+    if (id == OIS::MB_Right) {
+        mMouseLook = false;
+    }
+    CEGUI::System::getSingleton().injectMouseButtonUp(convertOisMouseButtonToCegui(id));
+    return true;
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.cpp (revision 3375)
+++ /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.cpp (revision 3375)
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "modelloader3ds.h"
+#include "myobjectnode.h"
+
+#include <modelloader/loader3ds.h>
+
+#include <d-collide/debug.h>
+#include <d-collide/world.h>
+#include <d-collide/proxy.h>
+#include <d-collide/shapes/mesh.h>
+#include <d-collide/shapes/mesh/vertex.h>
+
+#include <iostream>
+
+ModelLoader3ds::ModelLoader3ds() {
+    mLoader = new ModelLoader::Loader3ds();
+}
+
+ModelLoader3ds::~ModelLoader3ds() {
+    delete mLoader;
+}
+
+/*!
+ * Load a .3ds model from file. This method keeps the hierarchy in the .3ds file
+ * intact, by creating a \ref dcollide::Proxy hierarchy. If you want to load the
+ * model into a single \ref dcollide::Mesh, use loadFromFileInOneMesh instead.
+ *
+ * \return A new MyObjectNode containing the loaded object or NULL if loading
+ * failed for some reason. The caller is responsible for deleting the returned
+ * object.
+ *
+ * \param fileName An (absolute) filename to the .3ds file
+ * \param proxyType Used as proxyType parameter to the toplevel \ref MyObjectNode.
+ */
+MyObjectNode* ModelLoader3ds::loadFromFile(dcollide::World* world, const char* fileName, int proxyType) {
+    if (!fileName) {
+        // TODO: exception?
+        return 0;
+    }
+
+    if (proxyType < 0) {
+        proxyType = dcollide::PROXYTYPE_RIGID;
+    }
+    dcollide::Proxy* topProxy = mLoader->loadFromFile(world, fileName, (dcollide::ProxyTypes)proxyType);
+
+    if (!topProxy) {
+        return 0;
+    }
+
+    MyObjectNode* topObject = new MyObjectNode(topProxy);
+    if (!loadNode(topObject)) {
+        std::cerr << dc_funcinfo << "loading " << fileName << " failed" << std::endl;
+        delete topObject;
+        return false;
+    }
+    return topObject;
+}
+
+bool ModelLoader3ds::loadNode(MyObjectNode* node) {
+    if (!node) {
+        return false;
+    }
+    if (mLoader->getTransformationNodes().find(node->getProxy()) == mLoader->getTransformationNodes().end()) {
+        std::cerr << dc_funcinfo << "internal error: proxy not in map" << std::endl;
+        return false;
+    }
+    ModelLoader::Loader3ds::TransformationNode transformation = (*mLoader->getTransformationNodes().find(node->getProxy())).second;
+    node->resetTransformation();
+    node->translate(transformation.translation);
+    node->rotate(transformation.rotation);
+
+    const std::map<dcollide::Proxy*, ModelLoader::TextureInformation>& textureInformation = mLoader->getTextureInformation();
+    if (textureInformation.find(node->getProxy()) != textureInformation.end()) {
+        node->setTextureInformation((*textureInformation.find(node->getProxy())).second);
+    }
+
+    for (std::list<dcollide::Proxy*>::const_iterator it = node->getProxy()->getChildProxies().begin(); it != node->getProxy()->getChildProxies().end(); ++it) {
+        MyObjectNode* child = new MyObjectNode(*it);
+        loadNode(child);
+        node->addChild(child);
+    }
+    return true;
+}
+
+/*!
+ * See \ref ModelLoader::Loader3ds::loadFromFileToOneMesh
+ */
+MyObjectNode* ModelLoader3ds::loadFromFileInOneMesh(dcollide::World* world, const char* fileName, int proxyType) {
+    ModelLoader::TextureInformation textureInformation;
+    dcollide::Mesh* mesh = mLoader->loadFromFileToOneMesh(fileName, &textureInformation);
+    MyObjectNode* topObject = new MyObjectNode(world, mesh, proxyType);
+    topObject->setTextureInformation(textureInformation);
+    return topObject;
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.h (revision 1551)
+++ /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.h (revision 1551)
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_MODELLOADERPLY_H
+#define DCOLLIDE_MODELLOADERPLY_H
+
+class MyObjectNode;
+
+namespace dcollide {
+    class Proxy;
+    class Shape;
+    class World;
+}
+
+/*!
+ * Class that loads PLY files into d-collide data structures
+ * \author Andreas Beckermann <b_mann@gmx.de>
+ */
+class ModelLoaderPly {
+    public:
+        ModelLoaderPly();
+        virtual ~ModelLoaderPly();
+
+        MyObjectNode* loadFromFile(dcollide::World* world, const char* fileName, int proxyType = -1, double scale = 1.0);
+
+
+    protected:
+
+    private:
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.h (revision 1551)
+++ /d-collide/tags/1.0.0/testapp/modelloader/modelloader3ds.h (revision 1551)
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_MODELLOADER3DS_H
+#define DCOLLIDE_MODELLOADER3DS_H
+
+class MyObjectNode;
+
+namespace dcollide {
+    class Proxy;
+    class Shape;
+    class World;
+}
+
+namespace ModelLoader {
+    class Loader3ds;
+}
+
+/*!
+ * Class that loads .3ds files into d-collide data structures
+ * \author Andreas Beckermann <b_mann@gmx.de>
+ */
+class ModelLoader3ds {
+    public:
+        ModelLoader3ds();
+        virtual ~ModelLoader3ds();
+
+        MyObjectNode* loadFromFile(dcollide::World* world, const char* fileName, int proxyType = -1);
+        MyObjectNode* loadFromFileInOneMesh(dcollide::World* world, const char* fileName, int proxyType = -1);
+
+
+    protected:
+        bool loadNode(MyObjectNode* node);
+
+    private:
+        ModelLoader::Loader3ds* mLoader;
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.cpp (revision 2279)
+++ /d-collide/tags/1.0.0/testapp/modelloader/modelloaderply.cpp (revision 2279)
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "modelloaderply.h"
+#include "myobjectnode.h"
+
+#include <modelloader/loaderply.h>
+
+#include <d-collide/proxy.h>
+#include <d-collide/shapes/mesh.h>
+#include <d-collide/debug.h>
+
+#include <iostream>
+
+
+ModelLoaderPly::ModelLoaderPly() {
+}
+
+ModelLoaderPly::~ModelLoaderPly() {
+}
+
+MyObjectNode* ModelLoaderPly::loadFromFile(dcollide::World* world, const char* fileName, int proxyType, double scale) {
+    ModelLoader::LoaderPly loader;
+    dcollide::Mesh* mesh = loader.loadFromFileToOneMesh(fileName, scale);
+    if (!mesh) {
+        return 0;
+    }
+
+    MyObjectNode* topObject = new MyObjectNode(world, mesh, proxyType, false);
+
+    return topObject;
+}
+
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/odewrapper.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/odewrapper.cpp (revision 2660)
+++ /d-collide/tags/1.0.0/testapp/odewrapper.cpp (revision 2660)
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "odewrapper.h"
+
+#include <d-collide/proxy.h>
+#include <d-collide/collisioninfo.h>
+#include <d-collide/math/matrix.h>
+
+#include <d-collide/debugstream.h>
+#include <d-collide/exceptions/exception.h>
+
+/*!
+ * \brief convert a dcollide CollisionInfo into an ODE dContactGeom
+ * 
+ */
+dContactGeom convertCollisionInfo(dcollide::CollisionInfo& collision) {
+    dContactGeom result;
+    result.pos[0] = collision.collisionPoint.getX();
+    result.pos[1] = collision.collisionPoint.getY();
+    result.pos[2] = collision.collisionPoint.getZ();
+
+#ifdef __GNUC__
+#warning TODO remove normal length test in release version
+#endif
+    if (fabs(collision.normal.length() - 1) > 0.001){
+        collision.normal.normalize();
+        dcollide::error() << " A Collision normal vector with length != 1  has been handed to ODE. It has been normalized automatically.";
+        //throw dcollide::Exception("Collision normal vector with length == 1 handed to ODE.");
+    }
+    
+    result.normal[0] = collision.normal.getX();
+    result.normal[1] = collision.normal.getY();
+    result.normal[2] = collision.normal.getZ();
+
+    result.depth = (dReal) collision.penetrationDepth;
+
+    //Proxy.mUser1 is the pointer to the corresponding MyObjectNode
+    result.g1 = (dGeomID) collision.penetratingProxy->mUser1;
+    result.g2 = (dGeomID) collision.penetratedProxy->mUser1;
+
+    return result;
+}
+
+/*!
+ * \brief converts d-collide Matrix to ODE matrix
+ */
+void convertDcollideMatrix2Ode(const dcollide::Matrix& dcMatrix, dMatrix3& output) {
+    //note: dMatrix3 is a dReal[12]
+    //ODE expects the values in row-major ordering
+    output[0] = dcMatrix.getElement(0, 0);
+    output[1] = dcMatrix.getElement(0, 1);
+    output[2] = dcMatrix.getElement(0, 2);
+    output[3] = 0;
+    output[4] = dcMatrix.getElement(1, 0);
+    output[5] = dcMatrix.getElement(1, 1);
+    output[6] = dcMatrix.getElement(1, 2);
+    output[7] = 0;
+    output[8] = dcMatrix.getElement(2, 0);
+    output[9] = dcMatrix.getElement(2, 1);
+    output[10] = dcMatrix.getElement(2, 2);
+    output[11] = 0;
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/commandlineparser.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/commandlineparser.h (revision 1269)
+++ /d-collide/tags/1.0.0/testapp/commandlineparser.h (revision 1269)
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_COMMANDLINEPARSER_H
+#define DCOLLIDE_COMMANDLINEPARSER_H
+
+#include <list>
+#include <string>
+#include <vector>
+
+class CommandLineParser {
+    public:
+        CommandLineParser();
+        virtual ~CommandLineParser();
+
+        void addSwitch(const std::string& name, const std::string& shortName, const std::string& helpText);
+        void addStringOption(const std::string& name, const std::string& shortName, const std::string& parameterName, const std::string& helpText);
+
+        bool parseCommandLinesArgs(int argc, char** argv);
+
+        bool isOptionUsed(const std::string& name) const;
+        std::string getStringValue(const std::string& name) const;
+
+    protected:
+        enum OptionType {
+            OPTION_TYPE_SWITCH = 0,
+            OPTION_TYPE_STRING = 1
+        };
+
+    protected:
+        int findOptionIndex(const char* arg) const;
+        bool isOption(const char* arg, const std::string& name, const std::string& shortName = 0) const;
+        void printUsage();
+
+    private:
+        std::string mApplication;
+
+        std::vector<std::string> mOptionNames;
+        std::vector<std::string> mOptionShortNames;
+        std::vector<std::string> mOptionHelp;
+        std::vector<std::string> mOptionHelpStringParameter;
+        std::vector<int> mOptionType;
+        std::vector<bool> mOptionUsed;
+        std::vector<std::string> mOptionStringValue;
+};
+
+#endif
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/testapp.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/testapp.cpp (revision 3347)
+++ /d-collide/tags/1.0.0/testapp/testapp.cpp (revision 3347)
@@ -0,0 +1,504 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "testapp.h"
+#include "inputhandler.h"
+
+#include "gui.h"
+#include "framehistory.h"
+#include "scenes/scenemanager.h"
+#include "scenes/scenebase.h"
+#include "scenes/physicsscenebase.h"
+#include "dcollide-config_testapp.h"
+
+#include <d-collide/proxy.h>
+#include <d-collide/bvhnode.h>
+#include <d-collide/debugstream.h>
+#include <d-collide/broadphase/broadphase.h>
+#include <d-collide/broadphase/broadphasecollisions.h>
+#include <d-collide/collisioninfo.h>
+#include <d-collide/world.h>
+#include <d-collide/worldcollisions.h>
+#include <d-collide/timing.h>
+
+#include <OgreRoot.h>
+#include <OgreCamera.h>
+#include <OgreRenderWindow.h>
+#include <OgreSceneManager.h>
+#include <OgreWindowEventUtilities.h>
+#include <OgreFrameListener.h>
+#include <OgreLogManager.h>
+
+#include <iostream>
+
+//#define USE_CALLGRIND
+#ifdef USE_CALLGRIND
+#include <valgrind/callgrind.h>
+#endif
+
+#include "do_benchmark_hack.h"
+
+class MyWindowEventListener : public Ogre::WindowEventListener {
+    public:
+        MyWindowEventListener(Ogre::RenderWindow* window) {
+            mWindow = window;
+            mInputHandler = 0;
+            Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
+        }
+
+        ~MyWindowEventListener() {
+            Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
+        }
+
+        void setInputHandler(InputHandler* input) {
+            mInputHandler = input;
+        }
+
+        virtual void windowResized(Ogre::RenderWindow* window) {
+            if (window != mWindow) {
+                return;
+            }
+            if (mInputHandler) {
+                unsigned int width;
+                unsigned int height;
+                unsigned int colorDepth;
+                int left;
+                int top;
+                window->getMetrics(width, height, colorDepth, left, top);
+                mInputHandler->setWindowSize(width, height);
+            }
+        }
+
+        virtual void windowClosed(Ogre::RenderWindow* window) {
+            if (window != mWindow) {
+                return;
+            }
+            if (mInputHandler) {
+                mInputHandler->notifyWindowClosed();
+            }
+        }
+    private:
+        InputHandler* mInputHandler;
+        Ogre::RenderWindow* mWindow;
+};
+
+class MyOgreLogListener : public Ogre::LogListener {
+    public:
+        virtual void messageLogged(const Ogre::String& message, Ogre::LogMessageLevel m, bool maskDebug, const Ogre::String& logName);
+};
+
+void MyOgreLogListener::messageLogged(const Ogre::String& message, Ogre::LogMessageLevel m, bool maskDebug, const Ogre::String& logName) {
+    DCOLLIDE_UNUSED(logName);
+    DCOLLIDE_UNUSED(maskDebug);
+
+    const int ogreDebugArea = 80000;
+
+    switch (m) {
+        default:
+        case Ogre::LML_TRIVIAL:
+            break;
+        case Ogre::LML_NORMAL:
+            dcollide::debug(ogreDebugArea) << message;
+            break;
+        case Ogre::LML_CRITICAL:
+            dcollide::warning(ogreDebugArea) << message;
+            break;
+    }
+}
+
+/*!
+ * Constructs a TestApp object, however it does not initialize it. You must call
+ * \ref initialize before using it.
+ */
+TestApp::TestApp() {
+    mInputHandler = 0;
+    mGui = 0;
+    mOgreRoot = 0;
+    mSceneManager = 0;
+    mScene = 0;
+    mWindowEventListener = 0;
+    mViewport = 0;
+    mUseGUI = true;
+    mFrameCount = 0;
+    mMaxFrameCount = 0;
+    mMyOgreLogListener = new MyOgreLogListener();
+
+    mFrameHistory = new FrameHistory("Complete Frame");
+    mGraphicFrameHistory = new FrameHistory("Rendering");
+    mCollisionFrameHistory = new FrameHistory("Collision Detection");
+    mSceneUpdateHistory = new FrameHistory("Scene (incl. physics) Step");
+    mPhysicsStepHistory = new FrameHistory("Physics Step");
+
+#if DCOLLIDE_DO_BENCHMARK_HACK
+    mFrameHistory->setDestructionTextName_Hack(mFrameHistory->getName());
+    mGraphicFrameHistory->setDestructionTextName_Hack(mGraphicFrameHistory->getName());
+    mCollisionFrameHistory->setDestructionTextName_Hack(mCollisionFrameHistory->getName());
+    mSceneUpdateHistory->setDestructionTextName_Hack(mSceneUpdateHistory->getName());
+    mPhysicsStepHistory->setDestructionTextName_Hack(mPhysicsStepHistory->getName());
+    mFrameHistory->setRemoveFramesOlderThan(200000000);
+    mGraphicFrameHistory->setRemoveFramesOlderThan(200000000);
+    mCollisionFrameHistory->setRemoveFramesOlderThan(200000000);
+    mSceneUpdateHistory->setRemoveFramesOlderThan(200000000);
+    mPhysicsStepHistory->setRemoveFramesOlderThan(200000000);
+#endif
+
+    SceneManager::createSceneManager();
+}
+
+/*!
+ * Initialize the application, in particular initialize OGRE and OIS
+ * (the input system, see \ref InputHandler).
+ *
+ * \return TRUE on success, otherwise FALSE. The application should be
+ * quit, if initializing failed.
+ */
+bool TestApp::initialize() {
+    if (mOgreRoot) {
+        // already initialized
+        return true;
+    }
+    Ogre::String pluginFileName = ""; // don't use any plugin config file
+                                      // (we specify everything by code)
+    Ogre::String configFileName = ""; // don't use any config file
+                                      // (we specify everything by code)
+
+    // AB: we create our own logmanager - ogre will use that one.
+    Ogre::String logFileName = "Ogre.log"; // AB: name to identify the log - won't necessarily write to a file!
+    mOgreLogManager = new Ogre::LogManager();
+
+    // create a default log that ogre itself is going to use.
+    bool suppressFileOutput = true;
+    bool outputToConsole = false;
+    Ogre::Log* log = mOgreLogManager->createLog(logFileName, true, outputToConsole, suppressFileOutput);
+    log->addListener(mMyOgreLogListener);
+
+    // AB: atm we don't specify the 3rd parameter and thus use the default Ogre
+    //     log filename (Ogre.log in the current dir)
+    //     we could just use "" to disable the logfile.
+    mOgreRoot = new Ogre::Root(pluginFileName, configFileName);
+
+    // we use OpenGL
+    #if defined __APPLE__ || defined WIN32
+        mOgreRoot->loadPlugin("RenderSystem_GL");
+    #else
+        mOgreRoot->loadPlugin(DCOLLIDE_OGRE_PLUGIN_DIR "/RenderSystem_GL");
+    #endif
+
+    Ogre::RenderSystemList* renderSystemList = mOgreRoot->getAvailableRenderers();
+    if (renderSystemList->empty()) {
+        std::cerr << "Could not load any renderers?!" << std::endl;
+        return false;
+    }
+    Ogre::RenderSystem* renderSystem = renderSystemList->at(0);
+    mOgreRoot->setRenderSystem(renderSystem);
+    mOgreRoot->initialise(false);
+
+
+    // Create a window
+    int width = 1024;
+    int height = 768;
+    bool fullscreen = false;
+    mRenderWindow = mOgreRoot->createRenderWindow("d-collide test application", width, height, fullscreen);
+    if (!mUseGUI) {
+        mRenderWindow->setVisible(false);
+    }
+    mWindowEventListener = new MyWindowEventListener(mRenderWindow);
+
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_INSTALL_PREFIX + std::string("/resources/textures"), "FileSystem", "DCollideMaterials");
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_SOURCE_PREFIX + std::string("/resources/textures"), "FileSystem", "DCollideMaterials");
+    mOgreRoot->addResourceLocation("../resources/textures", "FileSystem", "DCollideMaterials");
+
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_INSTALL_PREFIX + std::string("/resources/models"), "FileSystem", "DCollideModels");
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_SOURCE_PREFIX + std::string("/resources/models"), "FileSystem", "DCollideModels");
+    mOgreRoot->addResourceLocation("../resources/models", "FileSystem", "DCollideModels");
+
+    // input
+    int windowHandle = 0;
+    mRenderWindow->getCustomAttribute("WINDOW", &windowHandle);
+    mInputHandler = new InputHandler(windowHandle);
+    mInputHandler->setTestApp(this);
+    mInputHandler->setWindowSize(width, height);
+    mWindowEventListener->setInputHandler(mInputHandler);
+
+    // GUI
+    mGui = new Gui(mOgreRoot, mRenderWindow);
+    mGui->setInputHandler(mInputHandler);
+    mGui->addFrameHistory(mFrameHistory, false);
+    mGui->addFrameHistory(mGraphicFrameHistory, true);
+    mGui->addFrameHistory(mSceneUpdateHistory, true);
+    mGui->addFrameHistory(mPhysicsStepHistory, true);
+    mGui->addFrameHistory(mCollisionFrameHistory, true);
+    if (!mGui->initialize()) {
+        std::cerr << "Could not initialize the GUI" << std::endl;
+        return false;
+    }
+
+    // our actual scene
+    changeCurrentScene("default");
+
+    if (!mScene) {
+        dcollide::error() << "NULL current scene: could not initialize default scene";
+        return false;
+    }
+
+    mInputHandler->initActions();
+
+    return true;
+}
+
+TestApp::~TestApp() {
+    delete mWindowEventListener;
+    delete mGui;
+    delete mInputHandler;
+
+    SceneManager::deleteSceneManager();
+
+    dCloseODE();
+
+    delete mOgreRoot;
+    delete mFrameHistory;
+    delete mGraphicFrameHistory;
+    delete mCollisionFrameHistory;
+    delete mSceneUpdateHistory;
+    delete mPhysicsStepHistory;
+
+    delete mMyOgreLogListener;
+    delete mOgreLogManager;
+}
+
+void TestApp::setCurrentScene(SceneBase* scene) {
+    mInputHandler->setScene(scene);
+
+    // Setup the renderer window (i.e. add a camera/viewport to it)
+    Ogre::Camera* camera = scene->getCamera();
+    if (!mViewport) {
+        mViewport = mRenderWindow->addViewport(camera);
+    }
+    mViewport->setCamera(camera);
+    camera->setAspectRatio(((Ogre::Real)mViewport->getActualWidth())
+                                / ((Ogre::Real)mViewport->getActualHeight()));
+    camera->setAutoAspectRatio(true);
+    camera->setNearClipDistance(5.0f); // AB: default is 100
+    camera->moveRelative(Ogre::Vector3(0.0f, 0.0f, 200.0f));
+    mInputHandler->setCamera(camera);
+    Ogre::SceneManager* manager = scene->getSceneManager();
+    mGui->setSceneManager(manager);
+    mGui->setSceneId(SceneManager::getSceneManager()->getSceneId(scene));
+    mGui->setSceneDescription(scene->getSceneDescription());
+
+    mScene = scene;
+
+    mInputHandler->forceToggleCallbackActivation();
+}
+
+
+/*!
+ * Starts the main event loop. This function does not return, unless the
+ * application is supposed to quit - either by closing the rendering window or
+ * by telling the \ref InputHandler to quit (see \ref InputHandler::queueQuit).
+ */
+void TestApp::startEventLoop() {
+    try {
+        Ogre::Timer timer;
+        unsigned long lastFrameStarted = timer.getMilliseconds();
+
+        mFrameCount = 0;
+
+    #ifdef USE_CALLGRIND
+        CALLGRIND_START_INSTRUMENTATION;
+        CALLGRIND_TOGGLE_COLLECT; // switch collect off
+    #endif
+        while (!mInputHandler->getWantQuit() && (!mRenderWindow->isClosed() || !mUseGUI)) {
+            mFrameHistory->startFrame();
+
+            // emulate Ogre's timeSinceLastFrame feature
+            unsigned long now = timer.getMilliseconds();
+            float timeSinceLastFrame = ((float)(now - lastFrameStarted)) / 1000.0f;
+            lastFrameStarted = now;
+
+            mInputHandler->captureInput(timeSinceLastFrame);
+            Ogre::WindowEventUtilities::messagePump();
+    #ifdef USE_CALLGRIND
+            CALLGRIND_TOGGLE_COLLECT; // switch collect on
+    #endif
+
+            // AB: note: a "scene frame" is not necessarily a "graphic frame".
+            // -> the collision detection library may be called more often or less
+            //    often than ogre.
+            //    usually we should NOT couple the scene speed to the rendering
+            //    speed, otherwise the scene will be VERY fast with a newer graphic
+            //    card
+            //
+            //    we do this here atm for the sake of simplicity only. we really
+            //    should use a timer instead.
+            if (!mInputHandler->getPause() || mInputHandler->getSingleStep()) {
+                mInputHandler->setSingleStep(false);
+                
+                dcollide::World* world = mScene->getCollisionWorld();
+                
+                if (!mInputHandler->isChecked("PauseMovements")) {
+                    mSceneUpdateHistory->startFrame();
+                    mScene->beginNextSceneFrame();
+
+                    if (mScene->getUsePhysics()) {
+                        mPhysicsStepHistory->setSkipped(false);
+                        mPhysicsStepHistory->startFrame();
+                        ((PhysicsSceneBase*)mScene)->doPhysicsStep();
+                        mPhysicsStepHistory->stopFrame();
+                    } else {
+                        mPhysicsStepHistory->setSkipped(true, "(Scene does not use physics)");
+                    }
+                    
+                    std::list<dcollide::Proxy*> toplevelproxies = world->getTopLevelProxies();
+                    
+                    for(std::list<dcollide::Proxy*>::iterator i = toplevelproxies.begin(); 
+                    	i!=toplevelproxies.end(); ++i ) {
+                    	if((*i)->getMoveFlags() & dcollide::Proxy::MOVEFLAG_DEFORMED) {
+                    		(const_cast<dcollide::BvhNode*>((*i)->getBvHierarchyNode()))->deform();
+                    	}
+                    }
+
+                    mScene->updateOgreRepresentations();
+
+                    mSceneUpdateHistory->stopFrame();
+                }
+
+
+                mCollisionFrameHistory->startFrame();
+                
+                // FIXME: not actually a "get" function: this calculates the collisions
+                unsigned int flags = dcollide::World::COLLISIONFLAG_NONE;
+                if (mInputHandler->getUseThreads()) {
+                    flags |= dcollide::World::COLLISIONFLAG_USE_THREADS;
+                }
+                if (!mInputHandler->isChecked("UsePipelining")) {
+                    flags |= dcollide::World::COLLISIONFLAG_DISABLE_PIPELINING;
+                }
+                if (mInputHandler->isChecked("SkipNarrowPhase")) {
+                    flags |= dcollide::World::COLLISIONFLAG_SKIP_NARROW_PHASE;
+                }
+                if (mInputHandler->isChecked("SkipMiddlePhase")) {
+                    flags |= dcollide::World::COLLISIONFLAG_SKIP_MIDDLE_PHASE;
+                }
+                mScene->calculateCollisions(flags);
+                mCollisionFrameHistory->stopFrame();
+
+                if (mUseGUI) {
+                    mScene->applyCollisions(*mScene->getWorldCollisions());
+                    if (!mGui->updateCollisionLabels(world, mScene->getWorldCollisions())) {
+                        mInputHandler->queueQuit();
+                    }
+                }
+            }
+
+    #ifdef USE_CALLGRIND
+            CALLGRIND_TOGGLE_COLLECT; // switch collect off
+    #endif
+
+            if (mUseGUI) {
+                if (!mGui->updateGui(mScene->getCollisionWorld(), mInputHandler->getPause())) {
+                    mInputHandler->queueQuit();
+                }
+
+                mGraphicFrameHistory->startFrame();
+                mOgreRoot->renderOneFrame();
+                mGraphicFrameHistory->stopFrame();
+            }
+
+            mFrameHistory->stopFrame();
+
+            mFrameCount++;
+            if (mMaxFrameCount > 0 && mFrameCount >= mMaxFrameCount) {
+                mInputHandler->queueQuit();
+            }
+        }
+    } catch (dcollide::Exception e) {
+        std::cerr   << "Unhandled exception reached main-program: \n"
+                << e.getErrorMessage() <<std::endl;
+        e.printBacktrace();
+        exit(1);
+    }
+}
+
+void TestApp::changeCurrentScene(const std::string& sceneId_) {
+    try {
+        std::string sceneId = sceneId_;
+        if (sceneId == "default") {
+            sceneId = SceneManager::getDefaultSceneId();
+        }
+        dcollide::debug() << dc_funcinfo << sceneId;
+        SceneBase* scene = SceneManager::getSceneManager()->createScene(sceneId, mOgreRoot);
+        if (scene == 0) {
+            dcollide::error() << dc_funcinfo << "could not create scene " << sceneId;
+            if (mScene) {
+                // continue using current scene
+                return;
+            } else {
+                if (sceneId == SceneManager::getDefaultSceneId()) {
+                    // use a fallback scene
+                    sceneId = "general";
+                }
+                dcollide::warning() << dc_funcinfo << "trying fallback scene " << sceneId;
+                scene = SceneManager::getSceneManager()->createScene(sceneId, mOgreRoot);
+                if (!scene) {
+                    throw dcollide::Exception("Could create neither default scene nor fallback scene");
+                }
+            }
+        }
+
+        if (!scene->initScene()) {
+            std::cerr << "Could not initialize the scene " << sceneId << std::endl;
+            SceneManager::getSceneManager()->deleteScene(scene);
+            return;
+        } else {
+            // force an initial update of Ogre scenenodes here
+            scene->updateOgreRepresentations(true);
+        }
+        if (scene) {
+            setCurrentScene(scene);
+        } else {
+            std::cerr << dc_funcinfo << "NULL scene created: don't know scene ID " << sceneId_ << std::endl;
+        }
+    } catch (dcollide::Exception e) {
+        std::cerr   << "Unhandled exception reached main-program: \n"
+                << e.getErrorMessage() <<std::endl;
+        e.printBacktrace();
+        exit(1);
+    }
+
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/uiaction.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/uiaction.h (revision 2350)
+++ /d-collide/tags/1.0.0/testapp/uiaction.h (revision 2350)
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_UIACTION_H
+#define DCOLLIDE_UIACTION_H
+
+#include <string>
+#include <list>
+
+namespace CEGUI {
+    class Renderer;
+    class System;
+    class Window;
+    class EventArgs;
+    class Checkbox;
+    class PushButton;
+}
+
+/*!
+ * \internal
+ */
+class UiActionSlotBase {
+    public:
+        virtual ~UiActionSlotBase();
+        virtual void call(bool parameter) = 0;
+        virtual void call() = 0;
+};
+
+/*!
+ * \internal
+ */
+template <class T> class UiActionSlot : public UiActionSlotBase {
+    public:
+        typedef void (T::*MemberFunctionVoidParameter)();
+        typedef void (T::*MemberFunctionBoolParameter)(bool parameter);
+
+    public:
+        inline UiActionSlot(MemberFunctionVoidParameter function, T* object);
+        inline UiActionSlot(MemberFunctionBoolParameter function, T* object);
+
+        inline virtual void call();
+        inline virtual void call(bool parameter);
+
+    private:
+        T* mObject;
+        MemberFunctionVoidParameter mFunctionVoidParameter;
+        MemberFunctionBoolParameter mFunctionBoolParameter;
+};
+
+template <class T> inline UiActionSlot<T>::UiActionSlot(MemberFunctionVoidParameter function, T* object) {
+    mObject = object;
+    mFunctionVoidParameter = function;
+    mFunctionBoolParameter = 0;
+}
+
+template <class T> inline UiActionSlot<T>::UiActionSlot(MemberFunctionBoolParameter function, T* object) {
+    mObject = object;
+    mFunctionBoolParameter = function;
+    mFunctionVoidParameter = 0;
+}
+
+template <class T> inline void UiActionSlot<T>::call(bool parameter) {
+    if (mFunctionBoolParameter) {
+        (mObject->*mFunctionBoolParameter)(parameter);
+    }
+}
+
+template <class T> inline void UiActionSlot<T>::call() {
+    if (mFunctionVoidParameter) {
+        (mObject->*mFunctionVoidParameter)();
+    }
+}
+
+class UiAction;
+class UiActionCollection {
+    public:
+        UiActionCollection();
+        ~UiActionCollection();
+
+        void addAction(UiAction* action);
+
+        void activateShortcut(int oisShortcut);
+
+        void setChecked(const std::string& actionName, bool c);
+        bool isChecked(const std::string& actionName) const;
+
+        const std::list<UiAction*>& getActions() const;
+
+    private:
+        std::list<UiAction*> mActions;
+};
+
+
+/*!
+ * \brief Action class for UI actions
+ *
+ * An UI "Action" is some kind of "one shot" event that the user has caused,
+ * usually by clicking some button or pressing a shortcut (note: "moving the
+ * mouse" is not a "one shot" event and thus not meant to be a UiAction).
+ *
+ * Such actions can provide different means to be activated, for example in a
+ * typical graphical text editor there is a menu entry "file open" and a
+ * shortcut "CTRl+O" which both do the same thing, i.e. are the same action.
+ *
+ * This class is meant to encapsulate such actions for our in the testapp and
+ * provide several means to activate the action: in particular usually a CEGUI
+ * widget and a keyboard shortcut (using OIS).
+ *
+ * See \ref UiToggleAction which implements the most important type of actions,
+ * i.e. checkbox-type actions.
+ *
+ * \author Andreas Beckermann <b_mann@gmx.de>
+ */
+class UiAction {
+    public:
+        UiAction(UiActionCollection* collection, const std::string& actionName);
+        virtual ~UiAction();
+
+        const std::string& getName() const;
+
+        virtual void setText(const std::string& text);
+        const std::string& getText() const;
+
+        void setOisShortcut(int shortcut);
+        int getOisShortcut() const;
+
+        std::string getOisShortcutString() const;
+
+        virtual void activate();
+
+    protected:
+        void addSlot(UiActionSlotBase* slot);
+
+    private:
+        std::list<UiActionSlotBase*> mSlots;
+        std::string mName;
+        std::string mText;
+        int mOisShortcut;
+};
+
+class UiPushButtonAction : public UiAction {
+    public:
+        UiPushButtonAction(UiActionCollection* collection, const std::string& actionName);
+        virtual ~UiPushButtonAction();
+
+        template<class T> inline void addActionCallback( void (T::*MemberFunction)(), T* object );
+
+        virtual void activate();
+
+    private:
+        void executeActionCallbacks();
+        bool ceguiCallbackStateChanged(const CEGUI::EventArgs&);
+
+    private:
+        CEGUI::PushButton* mButton;
+        std::list<UiActionSlotBase*> mActionCallbacks;
+};
+
+/*!
+ * \brief Toggle action class for UI actions
+ *
+ * \author Andreas Beckermann <b_mann@gmx.de>
+ */
+class UiToggleAction : public UiAction {
+    public:
+        UiToggleAction(UiActionCollection* collection, const std::string& actionName = "");
+        ~UiToggleAction();
+
+        void setChecked(bool c);
+        bool isChecked() const;
+
+        virtual void setText(const std::string& text);
+
+        virtual void activate();
+
+        void toggle();
+
+        void forceToggleCallbackActivation();
+
+        template<class T> inline void addToggleCallback( void (T::*MemberFunction)(), T* object );
+        template<class T> inline void addToggleCallback( void (T::*MemberFunction)(bool parameter), T* object );
+
+    private:
+        void addToggleCallbackInternal(UiActionSlotBase*);
+        bool ceguiCallbackStateChanged(const CEGUI::EventArgs&);
+        void executeToggleCallbacks();
+
+    private:
+        std::list<UiActionSlotBase*> mToggleCallbacks;
+        bool mChecked;
+
+        CEGUI::Checkbox* mCheckBox;
+};
+
+template<class T> inline void UiPushButtonAction::addActionCallback( void (T::*MemberFunction)(), T* object ) {
+    UiActionSlot<T>* s = new UiActionSlot<T>(MemberFunction, object);
+    mActionCallbacks.push_back(s);
+    addSlot(s);
+}
+
+template<class T> inline void UiToggleAction::addToggleCallback( void (T::*MemberFunction)(), T* object ) {
+    addToggleCallbackInternal(new UiActionSlot<T>(MemberFunction, object));
+}
+
+template<class T> inline void UiToggleAction::addToggleCallback( void (T::*MemberFunction)(bool parameter), T* object ) {
+    addToggleCallbackInternal(new UiActionSlot<T>(MemberFunction, object));
+}
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/framehistory.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/framehistory.h (revision 3335)
+++ /d-collide/tags/1.0.0/testapp/framehistory.h (revision 3335)
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_FRAMEHISTORY_H
+#define DCOLLIDE_FRAMEHISTORY_H
+
+#include <string>
+#include <list>
+
+namespace dcollide {
+    class Timing;
+    class PointInTime;
+}
+
+class Frame;
+
+class FrameHistory {
+    public:
+        FrameHistory(const std::string& name = "");
+        ~FrameHistory();
+
+        void setName(const std::string& name);
+        inline const std::string getName() const;
+
+        void startFrame();
+        Frame* stopFrame();
+        void addManualFrame(const dcollide::Timing& time);
+
+        void setSkipped(bool skipped, const std::string& skipMessage = "");
+        inline bool isSkipped() const;
+        inline const std::string& getSkipMessage() const;
+
+        void setRemoveFramesOlderThan(unsigned int ms);
+        unsigned int getRemoveFramesOlderThan() const;
+
+        const std::list<Frame*>& getFrames() const;
+
+        double getFpsAverage(bool extraPolate = false) const;
+        long int getUsAverage() const;
+
+        const dcollide::PointInTime& getAverageLastCalled() const;
+
+        void setDestructionTextName_Hack(const std::string& text);
+
+//        double calculateFpsAverageOfPreviousSeconds(int seconds) const;
+
+    protected:
+//        double calculateFpsAverage(const std::list<Frame*>::const_iterator& itBegin, const std::list<Frame*>::const_iterator& itAfterLast) const;
+        void removeOldFrames();
+
+        void addFrame(Frame*);
+        void removeFrame();
+
+    private:
+        std::string mDestructionText;
+        std::string mName;
+        std::list<Frame*> mFrames;
+        dcollide::PointInTime* mAverageLastCalled;
+        unsigned int mFrameCount;
+        Frame* mCurrentFrame;
+        unsigned int mRemoveFramesOlderThan;
+
+        long int mTimeSum;
+
+        bool mSkipped;
+        std::string mSkipMessage;
+};
+
+class Frame {
+    public:
+        Frame();
+        ~Frame();
+
+        void setTiming(const dcollide::Timing& t);
+        void stopTiming();
+
+        const dcollide::Timing& getTiming() const;
+
+    private:
+        dcollide::Timing* mTiming;
+};
+
+inline const std::string FrameHistory::getName() const {
+    return mName;
+}
+
+/*!
+ * \return TRUE if this frame history is currently being skipped (e.g. if this
+ * frame history measures physics, but the current scene does not use physics).
+ * FALSE otherwise (the default).
+ */
+inline bool FrameHistory::isSkipped() const {
+    return mSkipped;
+}
+
+/*!
+ * \return A message that can be displayed as reason why this frame history is
+ * skipped, or an empty string if no message was provided (see \ref setSkipped).
+ */
+inline const std::string& FrameHistory::getSkipMessage() const {
+    return mSkipMessage;
+}
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/myobjectnode.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/myobjectnode.cpp (revision 3359)
+++ /d-collide/tags/1.0.0/testapp/myobjectnode.cpp (revision 3359)
@@ -0,0 +1,988 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "myobjectnode.h"
+#include "mydeformableobjectnode.h"
+#include "ogresceneobjectfactory.h"
+#include "ogrematerials.h"
+#include "odewrapper.h" 
+
+#include <d-collide/world.h>
+#include <d-collide/proxy.h>
+#include <d-collide/bvhnode.h>
+#include <d-collide/boundingvolumes/boundingvolume.h>
+#include <d-collide/collisioninfo.h>
+#include <d-collide/debugstream.h>
+#include <d-collide/shapes/shapes.h>
+#include <d-collide/exceptions/exception.h>
+#include <d-collide/detectordeform/detectordeformmanager.h>
+#include <d-collide/detectordeform/detectordeformproxydata.h>
+
+#include <OgreSceneNode.h>
+#include <OgreManualObject.h>
+#include <OgreSceneManager.h>
+#include <OgreQuaternion.h>
+#include <ode/odewrapper.h>
+
+#include <iostream>
+#include <math.h>
+
+#include <d-collide/debugstream.h>
+
+#define DO_OGRE_DEBUG 1
+
+//GJ: scales the displayed length of visualized penetration vectors
+//TODO the user should be able to change this at runtime
+#define PENETRATION_DEPTH_SCALING_FACTOR 1
+
+/*!
+ * Create a new MyObjectNode object for \p shape. A \ref Proxy is created
+ * containing \p shape, with type flags \p proxyType.
+ *
+ * \param proxyType The \ref dcollide::Proxy::getProxyType() flags. If negative
+ * (the default) \ref dcollide::PROXYTYPE_RIGID is used.
+ */
+MyObjectNode::MyObjectNode(dcollide::World* world, dcollide::Shape* shape, int proxyType, bool useCulling, bool useTextures) {
+
+    mWorld = world;
+    mUseTextures = useTextures;
+    mUseCulling = useCulling;
+    mProxy = world->createProxy(shape, (dcollide::ProxyTypes)proxyType); // takes ownership of shape
+
+    mUseODE = false;
+    mODEGeom = 0;
+
+    mPrintDebugOutput = false;
+    mDebugOutputPrefix = "";
+
+    init();
+}
+
+/*!
+ * \overload
+ *
+ * This constructor takes an already created Proxy.
+ */
+MyObjectNode::MyObjectNode(dcollide::Proxy* proxy, bool useCulling, bool useTextures) {
+    if (!proxy) {
+        throw dcollide::NullPointerException("parameter proxy");
+    }
+
+    mUseTextures = useTextures;
+    mUseCulling = useCulling;
+    mProxy = proxy;
+    mWorld = mProxy->getWorld();
+
+    mUseODE = false;
+    mODEGeom = 0;
+
+    mPrintDebugOutput = false;
+    mDebugOutputPrefix = "";
+
+    init();
+}
+
+void MyObjectNode::init() {
+    mProxy->mUser1 = this;
+
+    mUniqueObjectName = generateUniqueObjectName();
+
+    mSceneNode = 0;
+    mNarrowPhaseResultsSceneNode = 0;
+    mNarrowPhaseResultsObject = 0;
+    mBoundingVolumeDirty = true;
+
+    if (mProxy && mProxy->getShape()) {
+        // textures
+        switch (mProxy->getShape()->getShapeType()) {
+            case dcollide::Shape::SHAPE_TYPE_BOX:
+            {
+                // we have a special texture for simple boxes
+
+                mTextureInformation.setTextured(true);
+
+                mTextureInformation.setTextureFileName("box.tga");
+                std::vector<dcollide::Vector3> texels;
+                texels.reserve(6 * 2 * 3); // 6 sides, each 2 triangles, each 3 vertices
+                // front side (vertices 6,5,4,5,6,7)
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+
+                // right side (vertices 3,1,5,3,5,7)
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+
+                // back side (vertices 2,0,1,2,1,3)
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+
+                // left side (vertices 0,2,4,2,6,4)
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+
+                // top side (vertices 0,4,1,1,4,5)
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+
+                // bottom side (vertices 2,3,6,3,7,6)
+                texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 0.0, 0.0));
+                texels.push_back(dcollide::Vector3(1.0, 1.0, 0.0));
+                texels.push_back(dcollide::Vector3(0.0, 1.0, 0.0));
+
+                mTextureInformation.setTexels(texels, false);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+}
+
+MyObjectNode::~MyObjectNode() {
+    if (mNarrowPhaseResultsSceneNode) {
+        Ogre::SceneManager* manager = mNarrowPhaseResultsSceneNode->getCreator();
+        if (mNarrowPhaseResultsObject) {
+            manager->destroyManualObject(mNarrowPhaseResultsObject);
+        }
+        manager->destroySceneNode(mNarrowPhaseResultsSceneNode->getName());
+    }
+
+    for (std::list<MyObjectNode*>::const_iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
+        delete *it;
+    }
+
+    if (mSceneNode) {
+        // AB: we currently assume that every ManualObject owns all
+        // materials that it uses!
+        // therefore we need to delete them, too
+        destroyAllOgreMaterials(mSceneNode);
+
+        destroyOgreSceneHierarchy(mSceneNode);
+        mSceneNode = 0;
+    }
+
+    for (std::list<Ogre::SceneNode*>::const_iterator it = mBVSceneNodes.begin(); it != mBVSceneNodes.end(); ++it) {
+        // AB: materials are shared among BV scene nodes of different
+        // MyObjectNode objects. therefore we dont need to delete them here.
+        destroyOgreSceneHierarchy(*it);
+    }
+    mBVSceneNodes.clear();
+
+    if (!mProxy->isInHierarchy()) {
+        delete mProxy;
+    }
+
+    delete mODEGeom;
+}
+
+std::string MyObjectNode::generateUniqueObjectName() {
+    static unsigned int objectNumber = 0;
+    std::stringstream ss;
+    ss << "MyObjectNode_";
+    ss << objectNumber;
+    objectNumber++;
+    return ss.str();
+}
+
+dcollide::Vector3 MyObjectNode::calculateBodyPosition(){
+    //code duplication, used in createphysicsbody also
+    dcollide::Vector3 transformedGravityOffset;
+    //transformedGravityOffset = nodeRotation * mODEGeom->getGravityOffset();
+    getRotation().transform(&transformedGravityOffset, mODEGeom->getGravityOffset());
+    return getWorldPosition() + transformedGravityOffset;
+}
+
+void MyObjectNode::resetTransformation() {
+    if (!getProxy()) {
+        return;
+    }
+
+    dcollide::Matrix identity;
+    mProxy->setTransformation(identity);
+
+    mBoundingVolumeDirty = true;
+}
+
+/*!
+ * \brief translates the Proxy,the OGRE node, and (if it exists) the physics body
+ *
+ */
+void MyObjectNode::translate(float x, float y, float z, bool respectOrientation) {
+    translate(dcollide::Vector3(x, y, z), respectOrientation);
+}
+
+/*!
+ * \brief translates the Proxy,the OGRE node, and (if it exists) the physics body
+ *
+ */
+void MyObjectNode::translate(const dcollide::Vector3& translation, bool respectOrientation) {
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "MyObjectNode::translate(translation: " << translation << ", respectOrientation: " << respectOrientation << ")" << std::endl;
+    }
+    if (!getProxy()) {
+        return;
+    }
+
+    if (mPrintDebugOutput) {
+        std::cout << mDebugOutputPrefix << "really translating!" << std::endl;
+    }
+    mProxy->translate(translation, respectOrientation);
+    
+    mBoundingVolumeDirty = true;
+    
+    if (getPhysicsBody()) {
+        if (mPrintDebugOutput) {
+            std::cout << mDebugOutputPrefix << "translating physics body!" << std::endl;
+        }
+
+        //calculate correct body position (with offset!)
+        dcollide::Vector3 bodyPosition = calculateBodyPosition();
+        
+        mODEGeom->setMoveNodeOnBodyMoved(false);
+        dBodySetPosition(getPhysicsBody(),  bodyPosition.getX(),
+                                            bodyPosition.getY(),
+                                            bodyPosition.getZ());
+        mODEGeom->setMoveNodeOnBodyMoved(true);
+    }
+}
+
+/*!
+ * \brief sets the absolute position of the Proxy,the node, and the physics body
+ * 
+ * \param movePhysicsBody controls wether the physics body (if it exists) should
+ *        be influenced by this command or not (default: true)
+*/
+void MyObjectNode::setPosition(float x, float y, float z, bool movePhysicsBody){
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->setPosition(x, y, z);
+
+    mBoundingVolumeDirty = true;
+
+    if (getPhysicsBody() && movePhysicsBody) {
+        dcollide::Vector3 bodyPosition = calculateBodyPosition();
+
+        mODEGeom->setMoveNodeOnBodyMoved(false);
+        dBodySetPosition(getPhysicsBody(),  bodyPosition.getX(),
+                                            bodyPosition.getY(),
+                                            bodyPosition.getZ());
+        mODEGeom->setMoveNodeOnBodyMoved(true);
+    }
+}
+
+
+void MyObjectNode::rotate(float angle, float x, float y, float z, bool respectOrientation) {
+    dcollide::Matrix m;
+    m.rotate(angle, x, y, z);
+    rotate(m, respectOrientation);
+}
+
+void MyObjectNode::setRotation(float angle, float x, float y, float z, bool movePhysicsBody) {
+    dcollide::Matrix m;
+    m.rotate(angle, x,y,z);
+    setRotation(m, movePhysicsBody);
+}
+
+/*!
+ * \brief rotates the Proxy,the OGRE node, and (if it exists) the physics body
+ *
+ * \param movePhysicsBody controls wether the physics body (if it exists) should
+ *        be influenced by this command or not (default: true)
+ */
+void MyObjectNode::setRotation(const dcollide::Matrix& rotation, bool movePhysicsBody) {
+    if (!getProxy()) {
+        return;
+    }
+
+    mProxy->setRotation(rotation);
+
+    mBoundingVolumeDirty = true;
+
+    if (getPhysicsBody() && movePhysicsBody) {
+        //rotating the node translates the body
+        //dBodySetPosition and dBodySetRotation both influence the node position
+        //prevent that the node is moved while doing this
+        mODEGeom->setMoveNodeOnBodyMoved(false);
+
+        dcollide::Vector3 bodyPosition = calculateBodyPosition();
+
+        //convert rotation matrix to ODE rotation matrix
+        dMatrix3 oderotation; //dReal[12]
+        convertDcollideMatrix2Ode(getRotation(), oderotation);
+
+        dBodySetRotation(getPhysicsBody(), oderotation);
+        dBodySetPosition(getPhysicsBody(),  bodyPosition.getX(),
+                                            bodyPosition.getY(),
+                                            bodyPosition.getZ());
+        mODEGeom->setMoveNodeOnBodyMoved(true);
+    }
+
+}
+
+/*!
+ * \brief rotates the Proxy,the OGRE node, and (if it exists) the physics body
+ *
+ *
+ */
+void MyObjectNode::rotate(const dcollide::Matrix& rotation, bool respectOrientation) {
+    if (!getProxy()) {
+        return;
+    }
+    
+    mProxy->rotate(rotation, respectOrientation);
+    
+    mBoundingVolumeDirty = true;
+    
+    if (getPhysicsBody()) {
+        dcollide::Vector3 bodyPosition = calculateBodyPosition();
+        dMatrix3 odeRotation;
+        convertDcollideMatrix2Ode(rotation, odeRotation);
+        
+        mODEGeom->setMoveNodeOnBodyMoved(false);
+        dBodySetRotation(getPhysicsBody(), odeRotation);
+        dBodySetPosition(getPhysicsBody(),  bodyPosition.getX(),
+                                            bodyPosition.getY(),
+                                            bodyPosition.getZ());
+        mODEGeom->setMoveNodeOnBodyMoved(true);
+    }
+
+}
+
+const std::list<MyObjectNode*>& MyObjectNode::getChildren() const {
+    return mChildren;
+}
+
+// WARNING: must be called BEFORE SceneBase::addTopLevelObject() is called!
+void MyObjectNode::addChild(MyObjectNode* child) {
+    if (!child) {
+        return;
+    }
+    if (!child->getProxy()) {
+        std::cerr << dc_funcinfo << "ERROR: NULL proxy" << std::endl;
+        return;
+    }
+    mChildren.push_back(child);
+    if (child->getProxy()->getParent() == 0) {
+        mProxy->addChild(child->getProxy());
+    }
+
+    mBoundingVolumeDirty = true;
+}
+
+/*!
+ * \return The internal dcollide proxy that represents this object.
+ */
+dcollide::Proxy* MyObjectNode::getProxy() const {
+    return mProxy;
+}
+
+/*!
+ * obsolete.
+ */
+void MyObjectNode::setRepeatedMovement(const dcollide::Vector3& start, const dcollide::Vector3& end, float speed) {
+    mMovementStart = start;
+    mMovementEnd = end;
+    mMovementSpeed = speed;
+}
+
+/*!
+ * obsolete.
+ */
+void MyObjectNode::setRepeatedMovementSpeed(float speed) {
+    mMovementSpeed = speed;
+}
+
+void MyObjectNode::recalculateBoundingVolumeOgreObjects() {
+    if (!getProxy()) {
+        std::cerr << "ERROR: NULL proxy" << std::endl;
+        return;
+    }
+
+    std::list<const dcollide::BvhNode*> bvhNodes;
+    if (getProxy()->getBvHierarchyNode()) {
+        bvhNodes.push_back(getProxy()->getBvHierarchyNode());
+    }
+
+    if (getProxy()->getProxyType() & dcollide::PROXYTYPE_DEFORMABLE) {
+        for (unsigned int index = 0; index < mWorld->getDetectorDeformManager()->getAlgorithms().size(); index++) {
+            dcollide::DetectorDeformProxyData* data = getProxy()->getDetectorDeformProxyData(index);
+            if (data && data->getDeformableBvhNode()) {
+                bvhNodes.push_back(data->getDeformableBvhNode());
+            }
+        }
+    }
+
+    for (std::list<const dcollide::BvhNode*>::const_iterator it = bvhNodes.begin(); it != bvhNodes.end(); ++it) {
+        recalculateBoundingVolumeOgreObjects(*it);
+    }
+    mBoundingVolumeDirty = false;
+}
+
+void MyObjectNode::recalculateBoundingVolumeOgreObjects(const dcollide::BvhNode* node) {
+    if (!node) {
+        std::cerr << "ERROR: NULL BvhNode" << std::endl;
+        return;
+    }
+    if (!node->mUser) {
+        dcollide::error() << dc_funcinfo << "NULL mUser pointer in BvhNode";
+        return;
+    }
+
+    Ogre::ManualObject* ogreObject = (Ogre::ManualObject*)node->mUser;
+    if (!node->getBoundingVolume()) {
+        dcollide::error() << dc_funcinfo << "NULL BoundingVolume";
+        ogreObject->clear();
+        return;
+    }
+
+    int volumeType = Ogre::any_cast<int>(ogreObject->getUserAny());
+    //std::cout << "volumeType" << volumeType << std::endl;
+    //std::cout << "volumeType_bvhnode" << node->getBoundingVolume()->getVolumeType() << std::endl;
+    if (node->getBoundingVolume()->getVolumeType() != volumeType) {
+        dcollide::error() << dc_funcinfo << "volumetype of node has changed since initial creation!";
+        ogreObject->clear();
+        OgreSceneObjectFactory::initOgreObjectForBoundingVolume(ogreObject, node->getBoundingVolume());
+    } else if (ogreObject->getNumSections() < 1) {
+        ogreObject->clear();
+        OgreSceneObjectFactory::initOgreObjectForBoundingVolume(ogreObject, node->getBoundingVolume());
+    } else {
+        ogreObject->beginUpdate(0);
+            OgreSceneObjectFactory::specifyBoundingVolumeLines(ogreObject, node->getBoundingVolume());
+        ogreObject->end();
+    }
+
+
+    const std::list<dcollide::BvhNode*>& children = node->getChildren();
+    for (std::list<dcollide::BvhNode*>::const_iterator it = children.begin(); it != children.end(); ++it) {
+        recalculateBoundingVolumeOgreObjects(*it);
+    }
+}
+
+/*!
+ * Set whether this MyObjectNode object is part of the broadphase collisions.
+ *
+ * If \p c is TRUE, this class may decide to display this object differently, if
+ * requested by the application (e.g. the boundingvolumes may be displayed in a
+ * different color.
+ */
+void MyObjectNode::setBroadPhaseCollision(bool c) {
+    // AB: for broadphase we color the bounding volume around the object
+    //     I would prefer to color the actual object, but that would be way
+    //     more difficult: we'd have to (recurisvely) color _all_
+    //     ManualObjects of that object, which could be a lot
+
+    if (!getProxy()) {
+        return;
+    }
+    const dcollide::BvhNode* bvhNode = getProxy()->getBvHierarchyNode();
+    if (!bvhNode) {
+        return;
+    }
+    Ogre::ManualObject* manual = static_cast<Ogre::ManualObject*>(bvhNode->mUser);
+    if (c) {
+        if (getProxy()->getParent()) {
+            std::cerr << dc_funcinfo << "can have broadphase collisions on toplevel proxies only" << std::endl;
+            return;
+        }
+        for (unsigned int i = 0; i < manual->getNumSections(); i++) {
+            manual->setMaterialName(i, OgreMaterials::getBoundingVolumeMaterial(true, false));
+        }
+    } else {
+        for (unsigned int i = 0; i < manual->getNumSections(); i++) {
+            manual->setMaterialName(i, OgreMaterials::getBoundingVolumeMaterial(false, false));
+        }
+    }
+}
+
+/*!
+ * Create ogre objects representing all narrowphase collisions added using \ref
+ * addNarrowPhaseCollision.
+ */
+void MyObjectNode::createNarrowPhaseCollisions() {
+    if (!mNarrowPhaseResultsSceneNode) {
+        std::cerr << dc_funcinfo << "NULL mNarrowPhaseResultsSceneNode" << std::endl;
+        return;
+    }
+    if (mNarrowPhaseResults.empty()) {
+        return;
+    }
+    if (!mNarrowPhaseResultsObject) {
+        mNarrowPhaseResultsObject = mNarrowPhaseResultsSceneNode->getCreator()->createManualObject(std::string("NarrowPhaseCollisionPoints_") + mUniqueObjectName);
+        mNarrowPhaseResultsSceneNode->attachObject(mNarrowPhaseResultsObject);
+    }
+
+    bool createNew = false;
+    if (mNarrowPhaseResultsObject->getNumSections() < 2) {
+        createNew = true;
+        mNarrowPhaseResultsObject->clear();
+    }
+
+    { // collision points
+        if (createNew) {
+            mNarrowPhaseResultsObject->begin(OgreMaterials::getNarrowPhaseCollisionPointsMaterial(), Ogre::RenderOperation::OT_POINT_LIST);
+        } else {
+            mNarrowPhaseResultsObject->beginUpdate(0);
+        }
+
+        for (std::list<dcollide::CollisionInfo>::iterator it= mNarrowPhaseResults.begin(); it != mNarrowPhaseResults.end(); ++it) {
+            dcollide::Vector3 p = (*it).collisionPoint;
+            mNarrowPhaseResultsObject->position(p.getX(), p.getY(), p.getZ());
+        }
+
+        mNarrowPhaseResultsObject->end();
+    }
+    { // collision normals
+        if (createNew) {
+            mNarrowPhaseResultsObject->begin(OgreMaterials::getNarrowPhaseNormalsMaterial(), Ogre::RenderOperation::OT_LINE_LIST);
+        } else {
+            mNarrowPhaseResultsObject->beginUpdate(1);
+        }
+
+        for (std::list<dcollide::CollisionInfo>::iterator it= mNarrowPhaseResults.begin(); it != mNarrowPhaseResults.end(); ++it) {
+            //TODO: define the penetration vector consistently
+            // to fit all shape-shape collisions and adapt the visualization
+            dcollide::Vector3 p = (*it).collisionPoint;
+                    //- (*it).normal * ((*it).penetrationDepth / 2);
+
+            // AB: note that we assume the normal is normalized!
+            // AB: we scale the length of the normal by the penetrationDepth. I
+            //     have no idea if that has any meaning whatsoever, but I don't
+            //     see any other way to visualize the penetration depth.
+            dcollide::Vector3 p2 = (*it).collisionPoint + (*it).normal *
+                ((*it).penetrationDepth) * PENETRATION_DEPTH_SCALING_FACTOR;
+
+            mNarrowPhaseResultsObject->position(p.getX(), p.getY(), p.getZ());
+            mNarrowPhaseResultsObject->position(p2.getX(), p2.getY(), p2.getZ());
+        }
+
+        mNarrowPhaseResultsObject->end();
+    }
+}
+
+void MyObjectNode::clearNarrowPhaseCollisions() {
+    mNarrowPhaseResults.clear();
+    setPenetratingObject(false);
+    setPenetratedObject(false);
+    if (mNarrowPhaseResultsObject) {
+        mNarrowPhaseResultsObject->clear();
+    }
+}
+
+/*!
+ * Store a narrowphase collision in this object for later display. Usually only
+ * one of the two objects in \p c should display a collision.
+ */
+void MyObjectNode::addNarrowPhaseCollision(const dcollide::CollisionInfo& c) {
+    mNarrowPhaseResults.push_back(c);
+}
+
+/*!
+ * Set the OGRE scenenode that this object is in. The scenenode in particular
+ * represents the translations and rotations of this proxy in OGRE.
+ *
+ * The given \p node should contain the entire hierarchy of this MyObjectNode,
+ * i.e. the \ref getChildren of this node should be represented in \p node by
+ * children, too. Also every \ref Shape object should be represented by one \ref
+ * Ogre::ManualObject in the appropriate node in the hierarchy.
+ *
+ * This class takes ownership of \p node and the entire hierarchy (i.e.
+ * including child-nodes and all \ref Ogre::ManualObject objects) and will
+ * delete it on destruction.
+ */
+void MyObjectNode::setOgreSceneNode(Ogre::SceneNode* node) {
+    if (mSceneNode) {
+        std::cerr << dc_funcinfo << "object already has an ogre scene node. cannot set a new one." << std::endl;
+        return;
+    }
+    if (!node) {
+        std::cerr << dc_funcinfo << "NULL node" << std::endl;
+        return;
+    }
+    mSceneNode = node;
+}
+
+/*!
+ * Set the list of OGRE scene nodes for the \ref BvhNode objects of this object.
+ *
+ * The \p nodes list contains exactly one \ref Ogre::SceneNode for each
+ * (toplevel) \ref BvhNode in \ref getProxy. A toplevel \ref BvhNode is either
+ * \ref Proxy::getBvHierarchyNode or a \ref
+ * DetectorDeformProxyData::getDeformableBvhNode (one such node per deformable
+ * algorithm may exist). If \ref getProxy is not deformable, there must be
+ * exactly one entry in \p nodes only.
+ *
+ * The first entry in \p nodes alway (!) must be the node corresponding to \ref
+ * Proxy::getBvHierarchyNode. It is expected that the order of the remaining
+ * nodes matches the order of \ref DetectorDeformManager::getAlgorithms() and
+ * that at most one node per algorithm appears. Also it is expected that the
+ * number of nodes does never change for this object.
+ *
+ * The list of nodes is used to destroy the nodes on destruction of this
+ * \ref MyObjectNode.
+ */
+void MyObjectNode::setOgreBVSceneNodes(const std::list<Ogre::SceneNode*>& nodes) {
+    if (!mBVSceneNodes.empty()) {
+        std::cerr << dc_funcinfo << "object already has ogre BV scene nodes. cannot set new ones." << std::endl;
+        return;
+    }
+    mBVSceneNodes = nodes;
+
+    if (mBVSceneNodes.empty()) {
+        std::cerr << dc_funcinfo << "empty list of nodes has been set! expected at least one entry for Proxy::getBvHierarchyNode()!" << std::endl;
+    }
+}
+
+/*!
+ * Set a scene node that should contain the narrowphase results of this object,
+ * i.e. everything created by \ref createNarrowPhaseCollisions (which uses \ref
+ * addNarrowPhaseCollision as input)
+ *
+ * This class takes ownership of \p node and will delete it on destruction.
+ */
+void MyObjectNode::setOgreNarrowPhaseResultsSceneNode(Ogre::SceneNode* node) {
+    if (mNarrowPhaseResultsSceneNode) {
+        std::cerr << dc_funcinfo << "object already has an narrowphase scene node. cannot set a new one." << std::endl;
+        return;
+    }
+    if (!node) {
+        std::cerr << dc_funcinfo << "NULL node" << std::endl;
+        return;
+    }
+    mNarrowPhaseResultsSceneNode = node;
+}
+
+/*!
+ * \brief get local coordinates of the node
+ */
+dcollide::Vector3 MyObjectNode::getTranslation() const {
+    if (!getProxy()) {
+        return dcollide::Vector3();
+    }
+    return getProxy()->getPosition();
+}
+
+/*!
+ * \brief get world coordinates of the node
+ */
+dcollide::Vector3 MyObjectNode::getWorldPosition() const {
+    if (!getProxy()) {
+        return dcollide::Vector3();
+    }
+    return getProxy()->getWorldTransformation().getPosition();
+}
+
+// FIXME: Misleading name. How can we distinguish between local and global rotation?
+dcollide::Matrix MyObjectNode::getRotation() const {
+    if (!getProxy()) {
+        return dcollide::Matrix();
+    }
+    return getProxy()->getRotation();
+}
+
+/*!
+ * \brief puts a physical, moveable representation into the physics simulation
+ *
+ * Will create a dBodyID and put it into the given world. The object will have
+ * the given total mass. The weight distribution around the reference point
+ * depends on the shape of this node's \ref dcollide::Proxy
+ *
+ * NOTE:    this function should be used for basic geometry only
+ *          (i.e Boxes, Spheres, Cylinders etc.).
+ *          For triangle Meshes, create your own dBodyID and
+ *          use \ref setPhysicsBody() instead.
+ *
+ * \param odeWorld the id of the (already created) ode world.
+ * \param space Deprecated. Use 0.
+ * \param totalMass the mass of the object.
+ */
+void MyObjectNode::createPhysicsBody(dWorldID odeWorld, dReal totalMass) {
+    //dcollide::debug() << dc_funcinfo;
+    if (!odeWorld) {
+        throw dcollide::NullPointerException("dWorldID odeWorld");
+    }
+
+    if (!mProxy->getShape()) {
+        std::cerr << "WARNING: cannot create physics body for a shapeless Proxy."<<std::endl;
+        return;
+    }
+
+    //do not create a body if it already exists
+    if (mODEGeom) {
+        std::cerr << "WARNING: physics body was already created for this Proxy."<<std::endl;
+        return;
+    }
+
+    if (mProxy->isInHierarchy()) {
+        dcollide::warning() << dc_funcinfo << "must be called before addTopLevelObject";
+        return;
+    }
+
+    mUseODE=true;
+    //create physical body for the shape
+
+    mODEGeom = new MyODETestAppGeom(this);
+    
+    dBodyID body = dBodyCreate(odeWorld);
+    dMass mass;
+
+    switch (mProxy->getShape()->getShapeType()) {
+        case dcollide::Shape::SHAPE_TYPE_BOX:
+            {
+                dcollide::Box* box = (dcollide::Box*)mProxy->getShape();
+                dMassSetBoxTotal(&mass, totalMass,  box->getDimension().getX(),
+                                                    box->getDimension().getY(),
+                                                    box->getDimension().getZ());
+                //the mass is now distributed around the reference point, which
+                //is the lower left corner of the box. To actually represent the
+                //box, we need to translate the mass to the center of the box
+                mODEGeom->setGravityOffset( dcollide::Vector3(
+                                                box->getDimension().getX() / 2,
+                                                box->getDimension().getY() / 2,
+                                                box->getDimension().getZ() / 2)
+                                           );
+
+                break;
+            }
+            case dcollide::Shape::SHAPE_TYPE_SPHERE:
+            {
+                dcollide::Sphere* sphere = (dcollide::Sphere*)mProxy->getShape();
+                dMassSetSphereTotal(&mass, totalMass,  sphere->getRadius());
+                break;
+            }
+            case dcollide::Shape::SHAPE_TYPE_CYLINDER:
+            {
+                dcollide::Cylinder* cylinder = (dcollide::Cylinder*)mProxy->getShape();
+                dMassSetCylinderTotal(&mass, totalMass,  3, cylinder->getRadius(), cylinder->getHeight());
+                //Translate mass from reference point (bottom sphere center) to
+                //center of gravity
+                mODEGeom->setGravityOffset( dcollide::Vector3(0, 0,cylinder->getHeight() / 2));
+                break;
+            }
+            //TODO: other shapes, see
+            //http://opende.sourceforge.net/wiki/index.php/Manual_%28Support_Functions%29
+            default:
+            {
+                std::cout<<"no special case found, creating aabb-box dBody" << std::endl;
+                //By default, use box mass adjustment, AABB-oriented
+                dcollide::Vector3 aabbMin = mProxy->getBvHierarchyNode()->getBoundingVolume()->getSurroundingAabbMin();
+
+                dcollide::Vector3 aabbDim = mProxy->getBvHierarchyNode()->getBoundingVolume()->getSurroundingAabbExtents();
+                
+                dMassSetBoxTotal(&mass, totalMass, aabbDim.getX(), aabbDim.getZ(), aabbDim.getZ());
+                mODEGeom->setGravityOffset( dcollide::Vector3(
+                                                aabbMin.getX() + aabbDim.getX() / 2,
+                                                aabbMin.getY() + aabbDim.getY() / 2,
+                                                aabbMin.getZ() + aabbDim.getZ() / 2)
+                                           );
+            }
+                break;
+    }//end switchcase
+
+
+    dBodySetMass(body, &mass);
+    dGeomSetBody((dGeomID)mODEGeom, body);
+    mODEGeom->setMoveNodeOnBodyMoved(false);
+    //move the body to the position of the node (+offset)
+    //go to node position + (node rotation matrix) * offset
+    dcollide::Vector3 bodyPosition = calculateBodyPosition();
+    dBodySetPosition(body, bodyPosition[0], bodyPosition[1], bodyPosition[2]);
+    
+    dMatrix3 odeRotation;
+    convertDcollideMatrix2Ode(getRotation(), odeRotation);
+    dBodySetRotation(body, odeRotation);
+    
+    //tell the mOdeTestappgeom that it is now at its valid position
+    //all future movements of the physics body will now move the node too
+    mODEGeom->setMoveNodeOnBodyMoved(true);
+
+    // should be pretty much a noop (we set the values that are already set)
+    dGeomMoved((dGeomID)mODEGeom);
+}
+
+/*!
+ *\brief use the given body for physics simulation
+ *
+ * OWNERSHIP notice: The Node takes ownership of the dBodyID
+ */
+void MyObjectNode::setPhysicsBody(dBodyID body) {
+    if (!mProxy->getShape()) {
+        std::cerr << "WARNING: cannot create physics body for a shapeless Proxy."<<std::endl;
+        return;
+    }
+
+    //do not create a body if it already exists
+    if (mODEGeom) {
+        std::cerr << "WARNING: physics body was already created for this Proxy."<<std::endl;
+        return;
+    }
+
+    //encapsulate the body in an MyODEGeom object and use it
+    mODEGeom = new MyODETestAppGeom(this);
+    dGeomSetBody((dGeomID)mODEGeom, body);
+}
+
+dBodyID MyObjectNode::getPhysicsBody() const {
+    if (mODEGeom) {
+        return mODEGeom->getBody();
+    }
+
+    return 0;
+}
+
+void MyObjectNode::destroyOgreSceneHierarchy(Ogre::SceneNode* top) {
+    if (!top) {
+        return;
+    }
+
+    Ogre::SceneManager* manager = top->getCreator();
+
+    std::list<Ogre::SceneNode*> nodes;
+    nodes.push_back(top);
+    while (!nodes.empty()) {
+        Ogre::SceneNode* node = nodes.front();
+        nodes.pop_front();
+        for (int i = 0; i < node->numChildren(); i++) {
+            nodes.push_back(static_cast<Ogre::SceneNode*>(node->getChild(i)));
+        }
+
+        if (node->numAttachedObjects() == 0) {
+            continue;
+        }
+        if (node->numAttachedObjects() > 1) {
+            dcollide::error() << "More than one object attached to an Ogre::SceneNode of MyObjectNode";
+        }
+
+        Ogre::MovableObject* object = node->getAttachedObject(0);
+        if (object->getMovableType() == Ogre::ManualObjectFactory::FACTORY_TYPE_NAME) {
+            Ogre::ManualObject* manual = static_cast<Ogre::ManualObject*>(object);
+            manager->destroyManualObject(manual);
+        }
+    }
+    top->removeAndDestroyAllChildren();
+    top->getCreator()->destroySceneNode(top->getName());
+}
+
+void MyObjectNode::destroyAllOgreMaterials(Ogre::SceneNode* top) {
+    if (!top) {
+        return;
+    }
+
+    std::list<Ogre::SceneNode*> nodes;
+    nodes.push_back(top);
+    while (!nodes.empty()) {
+        Ogre::SceneNode* node = nodes.front();
+        nodes.pop_front();
+        for (int i = 0; i < node->numChildren(); i++) {
+            nodes.push_back(static_cast<Ogre::SceneNode*>(node->getChild(i)));
+        }
+
+        if (node->numAttachedObjects() == 0) {
+            continue;
+        }
+        if (node->numAttachedObjects() > 1) {
+            dcollide::error() << "More than one object attached to an Ogre::SceneNode of MyObjectNode";
+        }
+
+        Ogre::MovableObject* object = node->getAttachedObject(0);
+        if (object->getMovableType() == Ogre::ManualObjectFactory::FACTORY_TYPE_NAME) {
+            Ogre::ManualObject* manual = static_cast<Ogre::ManualObject*>(object);
+            for (unsigned int i = 0; i < manual->getNumSections(); i++) {
+                OgreMaterials::destroyShapeMaterial(manual->getSection(i)->getMaterialName());
+            }
+        }
+    }
+}
+
+void MyObjectNode::setPenetratingObject(bool isPenetrating) {
+    mNarrowPhaseIsPenetrating = isPenetrating;
+}
+
+void MyObjectNode::setPenetratedObject(bool isPenetrated) {
+    mNarrowPhaseIsPenetrated = isPenetrated;
+}
+
+void MyObjectNode::updateMaterialForNarrowPhaseResults(bool displayNarrowPhaseResults) {
+    if (!mSceneNode) {
+//        dcollide::debug() << dc_funcinfo << "have no mSceneNode object";
+        return;
+    }
+    if (mSceneNode->numAttachedObjects() == 0) {
+        return;
+    }
+    if (mSceneNode->numAttachedObjects() > 1) {
+        dcollide::error() << "More than one object attached to an Ogre::SceneNode of MyObjectNode";
+    }
+
+    Ogre::MovableObject* object = mSceneNode->getAttachedObject(0);
+    if (object->getMovableType() == Ogre::ManualObjectFactory::FACTORY_TYPE_NAME) {
+        Ogre::ManualObject* manual = static_cast<Ogre::ManualObject*>(object);
+        for (unsigned int i = 0; i < manual->getNumSections(); i++) {
+            Ogre::Pass* pass = manual->getSection(i)->getMaterial()->getTechnique(0)->getPass(0);
+            if (displayNarrowPhaseResults) {
+                pass->setDiffuse(OgreMaterials::getShapeDiffuseColor(getTextureInformation(), mNarrowPhaseIsPenetrating, mNarrowPhaseIsPenetrated));
+            } else {
+                pass->setDiffuse(OgreMaterials::getShapeDiffuseColor(getTextureInformation()));
+            }
+        }
+    }
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/gui.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/gui.cpp (revision 3375)
+++ /d-collide/tags/1.0.0/testapp/gui.cpp (revision 3375)
@@ -0,0 +1,665 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "gui.h"
+#include "inputhandler.h"
+#include "framehistory.h"
+#include "scenes/scenemanager.h"
+#include "dcollide-config_testapp.h"
+
+#include <d-collide/world.h>
+#include <d-collide/worldcollisions.h>
+#include <d-collide/collisioninfo.h>
+#include <d-collide/bvhnode.h>
+#include <d-collide/timing.h>
+#include <d-collide/debug.h>
+#include <d-collide/debuglog.h>
+#include <d-collide/debugstream.h>
+#include <d-collide/broadphase/broadphase.h>
+#include <d-collide/broadphase/broadphasecollisions.h>
+
+#include <OgreRoot.h>
+#include <OgreCamera.h>
+#include <OgreRenderWindow.h>
+#include <OgreSceneManager.h>
+#include <OgreWindowEventUtilities.h>
+#include <OgreFrameListener.h>
+#include <OgreCEGUIRenderer.h>
+
+#include <CEGUI/CEGUISystem.h>
+#include <CEGUI/CEGUILogger.h>
+#include <CEGUI/CEGUIWindow.h>
+#include <CEGUI/CEGUIExceptions.h>
+#include <CEGUI/CEGUISchemeManager.h>
+#include <CEGUI/CEGUIWindowManager.h>
+#include <CEGUI/elements/CEGUIPushButton.h>
+#include <CEGUI/elements/CEGUICombobox.h>
+#include <CEGUI/elements/CEGUIListboxTextItem.h>
+#include <CEGUI/elements/CEGUIFrameWindow.h>
+
+#include <iostream>
+
+#include "do_benchmark_hack.h"
+
+dcollide::DebugStream operator<<(dcollide::DebugStream stream, const CEGUI::String& string) {
+    stream << string.c_str();
+    return stream;
+}
+
+/*!
+ * CEGUI on windows is compiled without rtti information. thus we can't
+ * use dynamic_cast on CEGUI objects.
+ * in order to not write many
+ *   if (o->getType()=="..:") {x = static_cast<...>(o);}
+ * statements over and over again, we use this macro.
+ * The ?: operator is used so that we can use it in simply
+ *   myVariable = CEGUI_CAST(...)
+ * lines.
+ *
+ * This macor either returns a pointer of type \p castTo, or a NULL pointer,
+ * depending whether \p windowName actually exists and is a window of type \p
+ * classType
+ */
+#define CEGUI_CAST(windowName, classType, castTo) \
+    (CEGUI::WindowManager::getSingleton().getWindow(windowName)->getType() == classType) ? \
+    (static_cast<castTo>(CEGUI::WindowManager::getSingleton().getWindow(windowName))) : \
+    0
+
+
+// AB: atm a dummy logger that simply discards all log messages.
+// this is atm mainly intended to stop cegui from creating a CEGUI.log without
+// asking.
+class MyCEGUILogger : public CEGUI::Logger {
+    public:
+        MyCEGUILogger();
+        ~MyCEGUILogger();
+
+        virtual void logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level = CEGUI::Standard);
+        virtual void setLogFilename(const CEGUI::String& filename, bool append = false);
+};
+
+MyCEGUILogger::MyCEGUILogger() {
+}
+
+MyCEGUILogger::~MyCEGUILogger() {
+}
+
+void MyCEGUILogger::logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level) {
+    const int ceguiDebugArea = 80001;
+
+    switch (level) {
+        case CEGUI::Errors:
+            dcollide::error(ceguiDebugArea) << message;
+            break;
+        case CEGUI::Standard:
+            dcollide::debug(ceguiDebugArea) << message;
+            break;
+        case CEGUI::Informative:
+            dcollide::info(ceguiDebugArea) << message;
+            break;
+        default:
+        case CEGUI::Insane:
+            break;
+    }
+}
+
+void MyCEGUILogger::setLogFilename(const CEGUI::String& filename, bool append) {
+    DCOLLIDE_UNUSED(filename);
+    DCOLLIDE_UNUSED(append);
+}
+
+
+class MyWindowEventListener : public Ogre::WindowEventListener {
+    public:
+        MyWindowEventListener(Ogre::RenderWindow* window) {
+            mWindow = window;
+            mInputHandler = 0;
+            Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
+        }
+
+        ~MyWindowEventListener() {
+            Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
+        }
+
+        void setInputHandler(InputHandler* input) {
+            mInputHandler = input;
+        }
+
+        virtual void windowResized(Ogre::RenderWindow* window) {
+            if (window != mWindow) {
+                return;
+            }
+            if (mInputHandler) {
+                unsigned int width;
+                unsigned int height;
+                unsigned int colorDepth;
+                int left;
+                int top;
+                window->getMetrics(width, height, colorDepth, left, top);
+                mInputHandler->setWindowSize(width, height);
+            }
+        }
+
+        virtual void windowClosed(Ogre::RenderWindow* window) {
+            if (window != mWindow) {
+                return;
+            }
+            if (mInputHandler) {
+                mInputHandler->notifyWindowClosed();
+            }
+        }
+    private:
+        InputHandler* mInputHandler;
+        Ogre::RenderWindow* mWindow;
+};
+
+/*!
+ * Constructs a Gui object, however it does not initialize it. You must call
+ * \ref initialize before using it.
+ */
+Gui::Gui(Ogre::Root* root, Ogre::RenderWindow* w) {
+    mOgreRoot = root;
+    mRenderWindow = w;
+    mInputHandler = 0;
+    mGuiRenderer = 0;
+    mGuiSystem = 0;
+    mGuiSheet = 0;
+
+    // SET TO 0 TO ENABLE BENCHMARKING (and then start testapp using --maxframes <number>
+#if !DCOLLIDE_DO_BENCHMARK_HACK
+    const int maxMs = 1000; // we average over maxMs ms
+#else
+#warning HACK: setRemoveFramesOlderThan() uses large dummy value
+    const int maxMs = 200000000; // we average over maxMs ms
+#endif
+    mCollisionsHistory.setRemoveFramesOlderThan(maxMs);
+    mBroadPhaseHistory.setRemoveFramesOlderThan(maxMs);
+    mMiddlePhaseHistory.setRemoveFramesOlderThan(maxMs);
+    mNarrowPhaseHistory.setRemoveFramesOlderThan(maxMs);
+    mPipelineHistory.setRemoveFramesOlderThan(maxMs);
+}
+
+Gui::~Gui() {
+    delete mGuiSystem;
+    delete mGuiRenderer;
+
+    // AB: do NOT delete the MyCEGUILogger object
+    //     -> CEGUI will automatically delete the singleton
+}
+
+void Gui::setInputHandler(InputHandler* h) {
+    mInputHandler = h;
+}
+
+void Gui::setSceneManager(Ogre::SceneManager* m) {
+    mGuiRenderer->setTargetSceneManager(m);
+}
+
+/*!
+ * Setup the CEGUI-based user interface. This needs an OGRE::SceneManager.
+ *
+ * \return true on success, false otherwise
+ */
+bool Gui::initialize() {
+    using namespace CEGUI;
+
+    if (!mInputHandler) {
+        std::cerr << dc_funcinfo << "ERROR: NULL input handler" << std::endl;
+        return false;
+    }
+
+    // add resource path for GUI-scheme and layout
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_INSTALL_PREFIX + std::string("/resources/cegui-skin"), "FileSystem");
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_SOURCE_PREFIX + std::string("/resources/cegui-skin"), "FileSystem");
+    mOgreRoot->addResourceLocation("../resources/cegui-skin", "FileSystem");
+
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_INSTALL_PREFIX + std::string("/resources"), "FileSystem");
+    mOgreRoot->addResourceLocation(DCOLLIDE_TESTAPP_SOURCE_PREFIX + std::string("/resources"), "FileSystem");
+    mOgreRoot->addResourceLocation("../resources", "FileSystem");
+
+    // AB: do NOT delete the object: CEGUI does so in CEGUI::System::~System()
+    new MyCEGUILogger();
+
+    mGuiRenderer = new OgreCEGUIRenderer(mRenderWindow);
+    mGuiSystem = new System(mGuiRenderer);
+
+    // load GUI scheme
+    try {
+        SchemeManager::getSingleton().loadScheme((utf8*)"DCollideSkin.scheme");
+    } catch (CEGUI::Exception e) {
+        std::cout << dc_funcinfo << "CEGUI exception when loading scheme: " << e.getMessage() << std::endl;
+        return false;
+    }
+
+    // set default cursor and font
+    mGuiSystem->setDefaultMouseCursor((utf8*)"DCollide", (utf8*)"MouseArrow");
+    MouseCursor::getSingleton().setImage("DCollide", "MouseMoveCursor");
+    mGuiSystem->setDefaultFont((utf8*)"Vera");
+    
+    // Move CEGUI mouse to (0,0)
+    CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();  
+    CEGUI::System::getSingleton().injectMouseMove(-mousePos.d_x,-mousePos.d_y);
+    // load and enable GUI sheet
+    try {
+        mGuiSheet = WindowManager::getSingleton().loadWindowLayout("testapp.layout");
+    } catch (CEGUI::Exception e) {
+        std::cout << dc_funcinfo << "CEGUI exception when loading window layout: " << e.getMessage() << std::endl;
+        return false;
+    }
+    mGuiSystem->setGUISheet(mGuiSheet);
+
+    WindowManager::getSingleton().getWindow((utf8*)"QuitButton")
+        ->subscribeEvent(
+            PushButton::EventClicked,
+            Event::Subscriber(&Gui::handleQuit, this));
+
+    WindowManager::getSingleton().getWindow((utf8*)"LegendButton")
+        ->subscribeEvent(
+            PushButton::EventClicked,
+            Event::Subscriber(&Gui::handleLegend, this));
+
+    // fill the combobox with all available scenes
+    Combobox* sceneBox = CEGUI_CAST("SceneSelectionBox", "DCollide/Combobox", CEGUI::Combobox*);
+    if (!sceneBox) {
+        std::cerr << dc_funcinfo << "cannot find TestApp/SceneSelectionBox" << std::endl;
+        return false;
+    }
+    
+    std::list<std::string> sceneTitles = SceneManager::getSceneManager()->getAvailableSceneTitles();
+    unsigned int index = 0; // we use index in the list as ID for the combobox item
+    colour white(1.0, 1.0, 1.0, 1.0);
+    for (std::list<std::string>::iterator it = sceneTitles.begin(); it != sceneTitles.end(); ++it) {
+        ListboxTextItem* item = new ListboxTextItem((utf8*)(*it).c_str(), index);
+        
+        // make the current selection in the combobox visible
+        item->setSelectionColours(white);
+        item->setTooltipText((*it).c_str());
+        item->setSelectionBrushImage("DCollide", "ListboxSelectionBrush");
+        
+        if ((*it) == SceneManager::getDefaultSceneId()) {
+            item->setSelected(true);
+        }
+        
+        sceneBox->addItem(item);
+        index++;
+    }
+    //sceneBox->setText(SceneManager::getDefaultSceneId().c_str());
+
+    sceneBox->subscribeEvent(Combobox::EventListSelectionAccepted,
+            Event::Subscriber(&Gui::handleSceneChange, this));
+    
+    mLegendWindow = CEGUI_CAST("LegendWindow", "DCollide/FrameWindow", CEGUI::FrameWindow*);
+    mLegendWindow->hide();
+    mLegendWindow->subscribeEvent(CEGUI::FrameWindow::EventCloseClicked,
+                                  Event::Subscriber(&Gui::handleLegend, this));
+
+    return true;
+}
+
+void Gui::addFrameHistory(const FrameHistory* h, bool extrapolate) {
+    if (extrapolate) {
+        mExtrapolateFrameHistories.push_back(h);
+    } else {
+        mFrameHistories.push_back(h);
+    }
+}
+
+bool Gui::handleQuit(const CEGUI::EventArgs&) {
+    if (mInputHandler) {
+        mInputHandler->queueQuit();
+    }
+    return true;
+}
+
+bool Gui::handleLegend(const CEGUI::EventArgs&) {
+    if (mLegendWindow->isVisible()) {
+        mLegendWindow->hide();
+    } else {
+        mLegendWindow->show();
+    }
+    
+    return true;
+}
+
+bool Gui::handleSceneChange(const CEGUI::EventArgs&) {
+    CEGUI::Combobox* sceneBox = CEGUI_CAST("SceneSelectionBox", "DCollide/Combobox", CEGUI::Combobox*);
+    if (!sceneBox) {
+        std::cerr << dc_funcinfo << "cannot find TestApp/SceneSelectionBox" << std::endl;
+        return false;
+    }
+    CEGUI::ListboxItem* item = sceneBox->getSelectedItem();
+    if (!item) {
+        return true;
+    }
+    unsigned int id = item->getID();
+    std::list<std::string> scenes = SceneManager::getSceneManager()->getAvailableSceneIds();
+
+    // AB: note: we don't use getText(), but rather the ID to identify the new
+    //     scene.
+    //     the text might not be the ID, but e.g. a i18n'ed name of it.
+    std::string newScene;
+    unsigned int i = 0;
+    for (std::list<std::string>::iterator it = scenes.begin(); it != scenes.end(); ++it) {
+        if (i == id) {
+            newScene = *it;
+            break;
+        }
+        i++;
+    }
+
+    if (newScene.empty()) {
+        std::cout << dc_funcinfo << "scene with combobox ID=" << id << " not found" << std::endl;
+        return true;
+    }
+
+    if (mInputHandler) {
+        mInputHandler->changeCurrentScene(newScene);
+    }
+
+    sceneBox->setText(item->getText());
+
+    return true;
+}
+
+/*!
+ * Called once per frame to display the current state (i.e. update labels etc.
+ *
+ * \return TRUE on success, FALSE on failure, indicating that the program should
+ * be aborted.
+ */
+bool Gui::updateGui(const dcollide::World* world, bool pause) {
+    updateStats();
+    //GJ: we update object count also in pause mode to update the labels on
+    //    scene changes in pause mode
+    return updateObjectCount(world);
+}
+
+/*!
+ * Update stats displayed on screen (ie. fps).
+ */
+void Gui::updateStats() {
+    using CEGUI::utf8;
+
+    if (mFrameHistories.empty() && mExtrapolateFrameHistories.empty()) {
+        return;
+    }
+
+    // we update every 2 seconds only
+    dcollide::PointInTime t;
+    t.addSeconds(-1);
+    if (!mFrameHistories.empty() && !mFrameHistories.front()->getAverageLastCalled().isBefore(t)) {
+        return;
+    } else if (!mExtrapolateFrameHistories.empty() && !mExtrapolateFrameHistories.front()->getAverageLastCalled().isBefore(t)) {
+        return;
+    }
+
+    std::stringstream ss;
+    for (std::list<const FrameHistory*>::const_iterator it = mFrameHistories.begin(); it != mFrameHistories.end(); ++it) {
+        if (it != mFrameHistories.begin()) {
+            ss << "\n";
+        }
+        double avg = (*it)->getFpsAverage(false);
+        ss.precision(2);
+        ss << (*it)->getName() << ": " << std::fixed << avg << " fps";
+    }
+    for (std::list<const FrameHistory*>::const_iterator it = mExtrapolateFrameHistories.begin(); it != mExtrapolateFrameHistories.end(); ++it) {
+        if (!mFrameHistories.empty() || it != mExtrapolateFrameHistories.begin()) {
+            ss << "\n";
+        }
+
+        // AB: these FPS values are extrapolated only, i.e. we display the FPS
+        // that _would_ have been achieved, if _only_ this task would have been
+        // performed.
+        // e.g. if we rendered 20 frames in one second, we have 20 FPS.
+        //      but if each frame took 1 ms to be rendered, we _could_ have
+        //      achieved 1000 FPS.
+        double avg = (*it)->getFpsAverage(true);
+        ss.precision(2);
+        ss << (*it)->getName() << ": " << std::fixed << avg << " fps (extrapolated)";
+    }
+
+    CEGUI::WindowManager::getSingleton().getWindow(
+            "FpsLabel")->setText(
+                (utf8*)ss.str().c_str());
+}
+
+/*!
+ * \return TRUE on success, FALSE on failure, indicating that the program should
+ * be aborted.
+ */
+bool Gui::updateCollisionLabels(dcollide::World* world, const dcollide::WorldCollisions* worldCollisions) {
+    using namespace CEGUI;
+
+    if (!worldCollisions) {
+        std::cerr << dc_funcinfo << "ERROR: NULL collisions" << std::endl;
+        return false;
+    }
+
+    dcollide::DebugLogEntry* entry = 0;
+    if (world->getDebugLog()) {
+        entry = world->getDebugLog()->getMostRecentEntry();
+    }
+    if (entry && entry->hasTiming("calculateAllCollisions()")) {
+        mCollisionsHistory.addManualFrame(entry->getTiming("calculateAllCollisions()"));
+    }
+    if (entry && entry->hasTiming("BroadPhase")) {
+        mBroadPhaseHistory.addManualFrame(entry->getTiming("BroadPhase"));
+    }
+    if (entry && entry->hasTiming("MiddlePhase")) {
+        mMiddlePhaseHistory.addManualFrame(entry->getTiming("MiddlePhase"));
+    }
+    if (entry && entry->hasTiming("NarrowPhase")) {
+        mNarrowPhaseHistory.addManualFrame(entry->getTiming("NarrowPhase"));
+    }
+    if (entry && entry->hasTiming("Pipeline")) {
+        mPipelineHistory.addManualFrame(entry->getTiming("Pipeline"));
+    }
+
+    // we update every 0.5 seconds only
+    dcollide::PointInTime t;
+    t.addMs(-500);
+    if (!mCollisionsHistory.getAverageLastCalled().isBefore(t)) {
+        return true;
+    }
+
+    Window* collisionsHeader = WindowManager::getSingleton().getWindow(
+            (utf8*)"CollisionResultsHeader");
+    Window* broadphaseLabel = WindowManager::getSingleton().getWindow(
+            (utf8*)"CollisionsBroadphase");
+    Window* middlephaseLabel = WindowManager::getSingleton().getWindow(
+            (utf8*)"CollisionsMiddlephase");
+    Window* narrowphaseLabel = WindowManager::getSingleton().getWindow(
+            (utf8*)"CollisionsNarrowphase");
+    Window* pipelineLabel = WindowManager::getSingleton().getWindow(
+            (utf8*)"TimingPipeline");
+    if (!collisionsHeader) {
+        std::cerr << dc_funcinfo << "ERROR: NULL collisionsHeader label" << std::endl;
+        return false;
+    }
+    if (!broadphaseLabel) {
+        std::cerr << dc_funcinfo << "ERROR: NULL broadphase label" << std::endl;
+        return false;
+    }
+    if (!middlephaseLabel) {
+        std::cerr << dc_funcinfo << "ERROR: NULL middlephase label" << std::endl;
+        return false;
+    }
+    if (!narrowphaseLabel) {
+        std::cerr << dc_funcinfo << "ERROR: NULL narrowphase label" << std::endl;
+        return false;
+    }
+    if (!pipelineLabel) {
+        std::cerr << dc_funcinfo << "ERROR: NULL pipeline label" << std::endl;
+        return false;
+    }
+    std::stringstream collisionsHeaderText;
+    std::stringstream broadphaseText;
+    std::stringstream middlephaseText;
+    std::stringstream narrowphaseText;
+    std::stringstream pipelineText;
+    collisionsHeaderText << "Collisions";
+    broadphaseText << "Broadphase: ";
+    middlephaseText << "Middlephase: ";
+    narrowphaseText << "Narrowphase: ";
+    pipelineText << "Pipeline";
+
+
+    const dcollide::BroadPhaseCollisions* broadCollisions = worldCollisions->getBroadPhaseCollisions();
+    const std::list<dcollide::BoundingVolumeCollision>& rigidCollisions = worldCollisions->getRigidBoundingVolumeCollisions();
+    const std::list<dcollide::BoundingVolumeCollision>& deformableCollisions = worldCollisions->getDeformableBoundingVolumeCollisions();
+    const std::list<dcollide::CollisionInfo>& narrowCollisions = worldCollisions->getNarrowPhaseCollisions();
+
+    // AB: we always display the counts of the most current frame, only the
+    // times is averaged!
+    broadphaseText << broadCollisions->getResults().size();
+    middlephaseText << (rigidCollisions.size() + deformableCollisions.size());
+    narrowphaseText << narrowCollisions.size();
+
+    collisionsHeaderText << " (total time: ";
+    broadphaseText << "  time: ";
+    middlephaseText << "  time: ";
+    narrowphaseText << "  time: ";
+    pipelineText << " time: ";
+
+    collisionsHeaderText << mCollisionsHistory.getUsAverage() << "us)";
+
+
+    // FIXME: we display "not available" when the values are not available in
+    // the _current_ frame, but when they are, we display an average over the
+    // previous few frames!
+    // -> if you switch between pipelined and non-pipeline mode, you have very
+    //    bad numbers for a few frames!
+    //    --> TODO: clear the history when we switch between pipelined and
+    //              non-pipelined mode
+    //              ideally even clear e.g. the middlephase history when we
+    //              switch between skipping and not-skipping of the middlephase.
+    //              maybe keep a boolean at this point whether the values for x
+    //              (with x being, broad/middle/narrow phase and pipeline) were
+    //              displayed last frame and if that boolean differs from the
+    //              current value, clear the history (except for the most recent
+    //              value)?
+
+#if DCOLLIDE_DO_BENCHMARK_HACK
+    mCollisionsHistory.setDestructionTextName_Hack("Collisions");
+#endif
+
+    if (entry && entry->hasTiming("BroadPhase")) {
+#if DCOLLIDE_DO_BENCHMARK_HACK
+        mBroadPhaseHistory.setDestructionTextName_Hack("BroadPhase");
+#endif
+        broadphaseText << mBroadPhaseHistory.getUsAverage() << "us";
+    } else {
+        mBroadPhaseHistory.setDestructionTextName_Hack("");
+        broadphaseText << "(not available)";
+    }
+    if (entry && entry->hasTiming("MiddlePhase")) {
+#if DCOLLIDE_DO_BENCHMARK_HACK
+        mMiddlePhaseHistory.setDestructionTextName_Hack("MiddlePhase");
+#endif
+        middlephaseText << mMiddlePhaseHistory.getUsAverage() << "us";
+    } else {
+        mMiddlePhaseHistory.setDestructionTextName_Hack("");
+        middlephaseText << "(not available)";
+    }
+    if (entry && entry->hasTiming("NarrowPhase")) {
+#if DCOLLIDE_DO_BENCHMARK_HACK
+        mNarrowPhaseHistory.setDestructionTextName_Hack("NarrowPhase");
+#endif
+        narrowphaseText << mNarrowPhaseHistory.getUsAverage() << "us";
+    } else {
+        mNarrowPhaseHistory.setDestructionTextName_Hack("");
+        narrowphaseText << "(not available)";
+    }
+    if (entry && entry->hasTiming("Pipeline")) {
+#if DCOLLIDE_DO_BENCHMARK_HACK
+        mPipelineHistory.setDestructionTextName_Hack("Pipeline");
+#endif
+        pipelineText << mPipelineHistory.getUsAverage() << "us";
+    } else {
+        mPipelineHistory.setDestructionTextName_Hack("");
+        pipelineText << "(not available)";
+    }
+
+
+
+    collisionsHeader->setText((utf8*)collisionsHeaderText.str().c_str());
+    broadphaseLabel->setText((utf8*)broadphaseText.str().c_str());
+    middlephaseLabel->setText((utf8*)middlephaseText.str().c_str());
+    narrowphaseLabel->setText((utf8*)narrowphaseText.str().c_str());
+    pipelineLabel->setText((utf8*)pipelineText.str().c_str());
+
+    return true;
+}
+
+bool Gui::updateObjectCount(const dcollide::World* world) {
+    if (!world) {
+        return false;
+    }
+
+    CEGUI::Window* proxies = CEGUI::WindowManager::getSingleton().getWindow("ProxyCount");
+    if (!proxies) {
+        std::cerr << dc_funcinfo << "NULL ProxyCount label" << std::endl;
+        return false;
+    }
+    std::stringstream proxiesText;
+    proxiesText << "Proxies (t/r/d): ";
+    proxiesText << world->getTopLevelProxies().size();
+    proxiesText << "/";
+    proxiesText << world->getRigidProxies().size();
+    proxiesText << "/";
+    proxiesText << world->getDeformableProxies().size();
+    proxies->setText(proxiesText.str().c_str());
+
+    return true;
+}
+
+void Gui::setSceneDescription(const std::string& text) {
+    CEGUI::Window* label = CEGUI_CAST("SceneDescription", "DCollide/StaticText", CEGUI::Window*);
+    if (label) {
+        label->setText(text);
+    }
+}
+
+void Gui::setSceneId(const std::string& text) {
+    CEGUI::Combobox* sceneBox = CEGUI_CAST("SceneSelectionBox", "DCollide/Combobox", CEGUI::Combobox*);
+    if (!sceneBox) {
+        std::cerr << dc_funcinfo << "cannot find SceneSelectionBox" << std::endl;
+        return;
+    }
+    sceneBox->setText(SceneManager::getSceneManager()->getSceneTitle(text));
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/main.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/main.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/main.cpp (revision 2943)
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "testapp.h"
+#include "scenes/scenemanager.h"
+#include "testappcommandline.h"
+
+#include <ode/odewrapper.h>
+
+#include <iostream>
+
+int main(int argc, char** argv) {
+    SceneManager::setDefaultSceneId("general");
+
+    TestApp app;
+
+    TestAppCommandLine cmd;
+    if (!cmd.parseAndApplyArgs(argc, argv, &app)) {
+        return 0;
+    }
+
+    // AB: note that even if we use ODE collision detection, we still need to
+    //     use MyODEGeom as interface.
+    //     this is required because a lot of functions in MyObjectNode depend on
+    //     it and we'd have to write two different versions of all that code
+    //     otherwise.
+    //
+    //     also note that as a result of this, comparing the speed of ODE and
+    //     d-collide directly with the current testapp design would be an UNFAIR
+    //     comparison!
+    //     in dGeomMoved() we always update MyODEGeom AND ODE's geom - in a real
+    //     ODE application the MyODEGeom overhead (which includes updating
+    //     d-collide) would not exist.
+    //     however this slows down dGeomMoved() only, not the actual collision
+    //     detection.
+    MyODEGeom::initializeODECollisionFunctions();
+
+    if (!app.initialize()) {
+        std::cerr << "Could not initialize the application" << std::endl;
+        return 1;
+    }
+
+    if (!cmd.applyArgsAfterInitialization(&app)) {
+        return 0;
+    }
+
+    app.startEventLoop();
+
+    return 0;
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.cpp (revision 2988)
+++ /d-collide/tags/1.0.0/testapp/ogresceneobjectfactory.cpp (revision 2988)
@@ -0,0 +1,768 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "ogresceneobjectfactory.h"
+#include "ogrematerials.h"
+#include "myobjectnode.h"
+
+#include <d-collide/proxy.h>
+#include <d-collide/shapes/shapes.h>
+#include <d-collide/math/plane.h>
+#include <d-collide/boundingvolumes/aabb.h>
+#include <d-collide/boundingvolumes/obb.h>
+#include <d-collide/boundingvolumes/kdop.h>
+#include <d-collide/boundingvolumes/boundingsphere.h>
+#include <d-collide/broadphase/hierarchicalgrid.h>
+#include <d-collide/bvhnode.h>
+#include <d-collide/debugstream.h>
+#include <d-collide/exceptions/exception.h>
+
+#include <OgreManualObject.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+#include <OgreString.h>
+#include <OgreMaterial.h>
+#include <OgreMaterialManager.h>
+
+int OgreSceneObjectFactory::mObjectNameNumber = 0;
+
+
+struct Line {
+    Line(const dcollide::Vector3& p, const dcollide::Vector3& v)
+        : point(p), vector(v) {
+    }
+    dcollide::Vector3 point;
+    dcollide::Vector3 vector;
+};
+
+
+
+OgreSceneObjectFactory::OgreSceneObjectFactory(Ogre::SceneManager* manager) {
+    mOgreSceneManager = manager;
+    if (!mOgreSceneManager) {
+        // TODO: exception
+        std::cerr << "a NULL scene manager is not allowed" << std::endl;
+    }
+}
+
+OgreSceneObjectFactory::~OgreSceneObjectFactory() {
+}
+
+// note: a NULL shape is perfectly valid here!
+Ogre::String OgreSceneObjectFactory::createUniqueObjectName(const dcollide::Shape*) {
+    mObjectNameNumber++;
+
+    std::stringstream ss;
+    ss << "OgreSceneObjectFactory_Object_";
+    ss << mObjectNameNumber;
+
+    // FIXME: can we always assume that Ogre::String is a std::String?
+    Ogre::String name;
+    ss >> name;
+
+    return name;
+}
+
+Ogre::String OgreSceneObjectFactory::createUniqueObjectName(const dcollide::BoundingVolume*) {
+    mObjectNameNumber++;
+
+    std::stringstream ss;
+    ss << "OgreSceneObjectFactory_Object_";
+    ss << mObjectNameNumber;
+
+    // FIXME: can we always assume that Ogre::String is a std::String?
+    Ogre::String name;
+    ss >> name;
+
+    return name;
+}
+
+/*!
+ * Creates an OGRE based hierarchy that reflects \p objectHierarchy
+ *
+ * The toplevel \ref Ogre::SceneNode represents the position and orientation of
+ * the dcollide::Proxy, whereas the Ogre object attached to it (see \ref
+ * Ogre::SceneNode::attachObject) represents the \ref dcollide::Shape.
+ *
+ * Each child proxy of the \p objectHierarchy is represented by yet another \ref
+ * Ogre::SceneNode.
+ *
+ * \param derivedScale The scale of all ancestors of \p objectHierarchy, NOT
+ * including the scale of \p objectHierarchy itself. This parameter is required
+ * because Ogre does not apply scaling values to translations (only to the
+ * vertices), but we apply scaling values to translations, too.
+ *
+ * \return A \ref Ogre::SceneNode object containing an Ogre representation of \p
+ * objectHierarchy. The node is NOT added to anything, it must be added to (e.g.) the \ref
+ * SceneManager::getRootSceneNode before it is of any use.
+ */
+Ogre::SceneNode* OgreSceneObjectFactory::createSceneHierarchy(MyObjectNode* objectHierarchy) {
+    if (!objectHierarchy) {
+        throw dcollide::NullPointerException("objectHierarchy");
+    }
+    if (!objectHierarchy->getProxy()) {
+        throw dcollide::NullPointerException("objectHierarchy->getProxy()");
+    }
+    if (objectHierarchy->getOgreSceneNode()) {
+        throw dcollide::Exception("ogre hierarchy already created");
+    }
+
+    Ogre::SceneNode* node = mOgreSceneManager->createSceneNode();
+
+    dcollide::Vector3 translation = objectHierarchy->getTranslation();
+
+    // AB: WARNING: we assume that the 3x3 matrix in the Proxy matrix is
+    //     actually a rotation matrix.
+    //     I have _NO_ idea what happens if it also contains things like
+    //     scalings or even worse stuff.
+    const dcollide::Matrix& matrix = objectHierarchy->getRotation();
+    Ogre::Matrix3 rot(matrix.getElement(0, 0), matrix.getElement(0, 1), matrix.getElement(0, 2),
+                matrix.getElement(1, 0), matrix.getElement(1, 1), matrix.getElement(1, 2),
+                matrix.getElement(2, 0), matrix.getElement(2, 1), matrix.getElement(2, 2));
+    Ogre::Quaternion quat(rot);
+
+    node->setPosition(translation[0], translation[1], translation[2]);
+    node->setOrientation(quat);
+
+    if (objectHierarchy->getProxy()->getShape()) {
+        Ogre::ManualObject* shapeObject
+            = createManualObject(
+                  objectHierarchy->getProxy()->getShape(),
+                  objectHierarchy->getTextureInformation(),
+                  objectHierarchy->getUseCulling(),
+                  objectHierarchy->getUseTextures()
+              );
+        node->attachObject(shapeObject);
+    }
+
+    const std::list<MyObjectNode*>& children = objectHierarchy->getChildren();
+    for (std::list<MyObjectNode*>::const_iterator it = children.begin(); it != children.end(); ++it) {
+        Ogre::SceneNode* child = createSceneHierarchy(*it);
+        (*it)->setOgreSceneNode(child);
+        node->addChild(child);
+    }
+
+    return node;
+}
+
+Ogre::SceneNode* OgreSceneObjectFactory::createBoundingVolumeSceneHierarchy(const dcollide::BvhNode* boundingVolumeNode) {
+    if (!boundingVolumeNode) {
+        throw dcollide::NullPointerException("boundingVolumeNode");
+    }
+    if (!boundingVolumeNode->getBoundingVolume()) {
+        throw dcollide::NullPointerException("boundingVolumeNode->getBoundingVolume()");
+    }
+
+    if (boundingVolumeNode->mUser) {
+        std::cerr << "ERROR: boundingVolumeNode->mUser is already used" << std::endl;
+        return 0;
+    }
+    Ogre::SceneNode* sceneNode = mOgreSceneManager->createSceneNode();
+
+    //std::cout << "create hierarchy volumeType_bvhnode" << boundingVolumeNode->getBoundingVolume()->getVolumeType() << std::endl;
+    Ogre::ManualObject* boundingVolumeObject = createManualObject(boundingVolumeNode->getBoundingVolume());
+    //int volumeTypeTemp = Ogre::any_cast<int>(boundingVolumeObject->getUserAny());
+    //std::cout << "create volumeType manualobject" << volumeTypeTemp << std::endl;
+
+    if (!boundingVolumeObject) {
+        std::cerr << "could not create ogre object from bounding volume" << std::endl;
+        return sceneNode;
+    }
+    sceneNode->attachObject(boundingVolumeObject);
+#ifdef __GNUC__
+#warning FIXME
+#endif
+    // AB: ugly. FIXME: use non-const parameter? or make mUser mutable?
+    const_cast<dcollide::BvhNode*>(boundingVolumeNode)->mUser = boundingVolumeObject;
+
+    const std::list<dcollide::BvhNode*>& children = boundingVolumeNode->getChildren();
+    for (std::list<dcollide::BvhNode*>::const_iterator it = children.begin(); it != children.end(); ++it) {
+        Ogre::SceneNode* child = createBoundingVolumeSceneHierarchy(*it);
+        sceneNode->addChild(child);
+    }
+
+    return sceneNode;
+}
+
+Ogre::SceneNode* OgreSceneObjectFactory::createHierarchicalGrid(
+        const dcollide::HierarchicalGrid* grid) {
+    if (!grid) {
+        return 0;
+    }
+    Ogre::SceneNode* sceneNode = mOgreSceneManager->createSceneNode();
+    Ogre::ManualObject* object = mOgreSceneManager->
+            createManualObject("OgreSceneObjectFactory_HierarchicalGrid");
+    object->setDynamic(true);
+    object->begin(OgreMaterials::getHierarchicalGridMaterial(),
+            Ogre::RenderOperation::OT_LINE_LIST);
+    specifyHierarchicalGrid(object, grid);
+    object->end();
+
+    sceneNode->attachObject(object);
+    return sceneNode;
+}
+
+/*!
+ * \return A \ref Ogre::ManualObject representing the \p shape. The object will
+ * NOT be attached to any scenenode and thus won't be deleted automatically
+ * before you use it in a \ref SceneNode::attachObject call.
+ */
+Ogre::ManualObject* OgreSceneObjectFactory::createManualObject(const dcollide::Shape* shape, const ModelLoader::TextureInformation& textureInformation, bool useCulling, bool useTextures) {
+    if (!shape) {
+        return 0;
+    }
+
+    Ogre::String name = createUniqueObjectName(shape);
+    Ogre::ManualObject* object = mOgreSceneManager->createManualObject(name);
+    Ogre::String materialName;
+    {
+        std::stringstream ss;
+        ss << name << "_Material";
+        ss >> materialName;
+    }
+
+    OgreMaterials::createShapeMaterial(materialName, textureInformation, useCulling, useTextures);
+
+    const dcollide::Mesh* mesh = const_cast<dcollide::Shape*>(shape)->getMesh();
+    const std::vector<dcollide::Triangle*>& triangles = mesh->getTriangles();
+
+    object->estimateVertexCount(triangles.size() * 3);
+    object->begin(materialName);
+        specifyTrianglesForShape(object, shape, textureInformation, useTextures);
+    object->end();
+
+    return object;
+}
+
+Ogre::ManualObject* OgreSceneObjectFactory::createManualObject(const dcollide::BoundingVolume* boundingVolume) {
+    if (!boundingVolume) {
+        return 0;
+    }
+
+    Ogre::String name = createUniqueObjectName(boundingVolume);
+    Ogre::ManualObject* object = mOgreSceneManager->createManualObject(name);
+
+    initOgreObjectForBoundingVolume(object, boundingVolume);
+    return object;
+}
+
+void OgreSceneObjectFactory::initOgreObjectForBoundingVolume(Ogre::ManualObject* object, const dcollide::BoundingVolume* boundingVolume) {
+    if (!boundingVolume) {
+        object->setUserAny(Ogre::Any((int)0));
+        return;
+    }
+
+    object->setUserAny(Ogre::Any((int)boundingVolume->getVolumeType()));
+    object->setDynamic(true);
+
+    switch (boundingVolume->getVolumeType()) {
+        case dcollide::BV_TYPE_AABB:
+            initOgreObjectForAabb(object, static_cast<const dcollide::Aabb*>(boundingVolume));
+            break;
+        case dcollide::BV_TYPE_KDOP:
+            initOgreObjectForKdop(object, static_cast<const dcollide::Kdop*>(boundingVolume));
+            break;
+        case dcollide::BV_TYPE_SPHERE:
+            initOgreObjectForSphere(object, static_cast<const dcollide::BoundingSphere*>(boundingVolume));
+            break;
+        case dcollide::BV_TYPE_OBB:
+            initOgreObjectForObb(object, static_cast<const dcollide::Obb*>(boundingVolume));
+            break;
+
+        // AB: do NOT add a default! -> this way we get compiler warnings if we
+        //     forget a type
+    }
+}
+
+void OgreSceneObjectFactory::initOgreObjectForAabb(Ogre::ManualObject* object, const dcollide::Aabb* aabb) {
+    if (!object) {
+        // TODO: exception
+        return;
+    }
+    if (!aabb) {
+        // TODO: exception
+        return;
+    }
+    Ogre::String material = OgreMaterials::getBoundingVolumeMaterial();
+    object->estimateVertexCount(8);
+    object->estimateIndexCount(24);
+
+    dcollide::Vector3 min = aabb->getMin();
+    dcollide::Vector3 max = aabb->getMax();
+    object->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
+        specifyBoundingVolumeLinesForAabb(object, aabb);
+    object->end();
+}
+
+void OgreSceneObjectFactory::initOgreObjectForObb(Ogre::ManualObject* object,
+        const dcollide::Obb* obb) {
+    if (!object) {
+        // TODO: exception
+        return;
+    }
+    if (!obb) {
+        // TODO: exception
+        return;
+    }
+    Ogre::String material = OgreMaterials::getBoundingVolumeMaterial();
+    object->estimateVertexCount(8);
+    object->estimateIndexCount(24);
+
+    object->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
+        specifyBoundingVolumeLinesForObb(object, obb);
+    object->end();
+}
+
+void OgreSceneObjectFactory::initOgreObjectForKdop(Ogre::ManualObject* object, const dcollide::Kdop* kdop) {
+    if (!object) {
+        // TODO: exception
+        return;
+    }
+    if (!kdop) {
+        // TODO: exception
+        return;
+    }
+    Ogre::String material = OgreMaterials::getBoundingVolumeMaterial();
+
+    object->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
+        specifyBoundingVolumeLinesForKdop(object, kdop);
+    object->end();
+}
+
+void OgreSceneObjectFactory::initOgreObjectForSphere(Ogre::ManualObject* object, const dcollide::BoundingSphere* sphere) {
+    if (!object) {
+        // TODO: exception
+        return;
+    }
+    if (!sphere) {
+        // TODO: exception
+        return;
+    }
+    Ogre::String material = OgreMaterials::getBoundingVolumeMaterial();
+
+    object->begin(material, Ogre::RenderOperation::OT_TRIANGLE_LIST);
+        specifyBoundingVolumeTrianglesForSphere(object, sphere);
+    object->end();
+}
+
+void OgreSceneObjectFactory::specifyBoundingVolumeLines(Ogre::ManualObject* object, const dcollide::BoundingVolume* bv) {
+    if (!bv) {
+        dcollide::error() << dc_funcinfo << "NULL BoundingVolume";
+        return;
+    }
+    switch (bv->getVolumeType()) {
+        case dcollide::BV_TYPE_AABB:
+            specifyBoundingVolumeLinesForAabb(object, static_cast<const dcollide::Aabb*>(bv));
+            break;
+        case dcollide::BV_TYPE_KDOP:
+            specifyBoundingVolumeLinesForKdop(object, static_cast<const dcollide::Kdop*>(bv));
+            break;
+        case dcollide::BV_TYPE_SPHERE:
+            // FIXME: we are in specifyBoundingVolume_Lines_, but spheres used
+            // triangles
+            specifyBoundingVolumeTrianglesForSphere(object, static_cast<const dcollide::BoundingSphere*>(bv));
+            break;
+        case dcollide::BV_TYPE_OBB:
+            specifyBoundingVolumeLinesForObb(object, static_cast<const
+                    dcollide::Obb*>(bv));
+            break;
+
+        // AB: do NOT add a default! -> this way we get compiler warnings if we
+        //     forget a type
+    }
+
+    dcollide::Vector3 bvMin = bv->getSurroundingAabbMin();
+    dcollide::Vector3 bvMax = bv->getSurroundingAabbMax();
+    Ogre::Vector3 min(bvMin[0], bvMin[1], bvMin[2]);
+    Ogre::Vector3 max(bvMax[0], bvMax[1], bvMax[2]);
+    Ogre::AxisAlignedBox aabb(min, max);
+    object->setBoundingBox(aabb);
+}
+
+void OgreSceneObjectFactory::specifyBoundingVolumeLinesForAabb(Ogre::ManualObject* object, const dcollide::Aabb* aabb) {
+    if (!aabb) {
+        return;
+    }
+    dcollide::Vector3 min = aabb->getMin();
+    dcollide::Vector3 max = aabb->getMax();
+
+    object->position(min.getX(), min.getY(), min.getZ());
+    object->position(min.getX(), min.getY(), max.getZ());
+    object->position(min.getX(), max.getY(), min.getZ());
+    object->position(min.getX(), max.getY(), max.getZ());
+    object->position(max.getX(), min.getY(), min.getZ());
+    object->position(max.getX(), min.getY(), max.getZ());
+    object->position(max.getX(), max.getY(), min.getZ());
+    object->position(max.getX(), max.getY(), max.getZ());
+
+    object->index(2);
+    object->index(0);
+
+    object->index(1);
+    object->index(0);
+
+    object->index(1);
+    object->index(3);
+
+    object->index(2);
+    object->index(3);
+
+    object->index(4);
+    object->index(5);
+
+    object->index(6);
+    object->index(4);
+
+    object->index(5);
+    object->index(7);
+
+    object->index(6);
+    object->index(7);
+
+    object->index(4);
+    object->index(0);
+
+    object->index(1);
+    object->index(5);
+
+    object->index(2);
+    object->index(6);
+
+    object->index(3);
+    object->index(7);
+}
+
+void OgreSceneObjectFactory::specifyBoundingVolumeLinesForObb(
+        Ogre::ManualObject* object, const dcollide::Obb* obb) {
+    if (!obb) {
+        return;
+    }
+
+    dcollide::Vector3* verts = obb->getVertices();
+
+    for (int i = 0; i<8;++i) {
+        object->position(verts[i].getX(),verts[i].getY(),verts[i].getZ());
+    }
+
+    object->index(2);
+    object->index(0);
+
+    object->index(1);
+    object->index(0);
+
+    object->index(1);
+    object->index(3);
+
+    object->index(2);
+    object->index(3);
+
+    object->index(4);
+    object->index(5);
+
+    object->index(6);
+    object->index(4);
+
+    object->index(5);
+    object->index(7);
+
+    object->index(6);
+    object->index(7);
+
+    object->index(4);
+    object->index(0);
+
+    object->index(1);
+    object->index(5);
+
+    object->index(2);
+    object->index(6);
+
+    object->index(3);
+    object->index(7);
+
+    delete[] verts;
+}
+
+void OgreSceneObjectFactory::specifyBoundingVolumeLinesForKdop(Ogre::ManualObject* object, const dcollide::Kdop* kdop) {
+    if (!kdop) {
+        return;
+    }
+
+    /*
+     * This code sucks terribly from an efficiency POV: it works in O(k^3).
+     *
+     * Unfortunately the other solutions I tried didn't work out:
+     * 1. intersecting 3 neighboring planes to find a point and then connecting
+     *    them properly did not work: sometimes the intersection of 3
+     *    neighboring planes is outside the k-DOP. figuring out the correct
+     *    planes in these cases is .. well, I did not manage to do that.
+     * 2. Starting by the lines of a AABB and then intersecting the lines with
+     *    each of the k-DOP planes should work, but whenever a line is
+     *    completely behind a plane (i.e. not visible), we have to add two or
+     *    more new lines. I could not find a "good" way to figure out which
+     *    lines exactly to add (more precisely: which NOT to add. I could find
+     *    all of the points, but simply connecting all of them with each other
+     *    would result in too many lines)
+     *
+     * So we go with a brute force method here: intersect each plane with each
+     * plane (O(k^2)) which gives us a set of lines. Each of these lines is then
+     * intersected with each of the planes to get the correct line segments (or
+     * discard the line entirely).
+     *
+     * It ain't nice, it ain't fast, but it works.
+     */
+
+    std::vector<dcollide::Plane> planes;
+    planes.reserve(kdop->getK());
+    for (int i = 0; i < kdop->getK(); i++) {
+        planes.push_back(dcollide::Plane(kdop->getPlaneNormal(i), kdop->getDistanceOfPlaneToOrigin(i)));
+    }
+
+    std::list<Line> lines;
+    dcollide::Vector3 intersectionPoint;
+    dcollide::Vector3 intersectionVector;
+    for (std::vector<dcollide::Plane>::iterator planeIt = planes.begin(); planeIt != planes.end(); ++planeIt) {
+        const dcollide::Plane& plane1 = (*planeIt);
+        std::vector<dcollide::Plane>::iterator planeIt2 = planeIt;
+        ++planeIt2;
+        for (; planeIt2 != planes.end(); ++planeIt2) {
+            const dcollide::Plane& plane2 = (*planeIt2);
+            if (!plane1.intersectPlane(plane2, &intersectionPoint, &intersectionVector)) {
+                continue;
+            }
+            lines.push_back(Line(intersectionPoint, intersectionVector));
+        }
+    }
+
+    for (std::list<Line>::iterator it = lines.begin(); it != lines.end(); ++it) {
+        const Line& line = (*it);
+        std::list<dcollide::Vector3> points;
+        for (std::vector<dcollide::Plane>::iterator planeIt = planes.begin(); planeIt != planes.end(); ++planeIt) {
+            const dcollide::Plane& plane = (*planeIt);
+            if (plane.intersectLine(line.point, line.vector, &intersectionPoint)) {
+                points.push_back(intersectionPoint);
+            }
+        }
+
+        std::vector<dcollide::Vector3> lineSegmentPoints;
+        for (std::list<dcollide::Vector3>::iterator it = points.begin(); it != points.end(); ++it) {
+            bool behind = false;
+            for (std::vector<dcollide::Plane>::iterator planeIt = planes.begin(); planeIt != planes.end(); ++planeIt) {
+                const dcollide::Plane& plane = (*planeIt);
+                if (plane.isOnPlane(*it)) {
+                    continue;
+                }
+                bool a = plane.isInFrontOfPlane(*it);
+                bool b = plane.isBehindPlane(*it);
+                if (a && b) {
+                    continue;
+                }
+                if (a) {
+                    behind = true;
+                    break;
+                }
+            }
+            if (!behind) {
+                lineSegmentPoints.push_back(*it);
+            }
+        }
+
+        if (lineSegmentPoints.size() >= 2) {
+            for (unsigned int i = 0; i < lineSegmentPoints.size(); i++) {
+                for (unsigned int j = i + 1; j < lineSegmentPoints.size(); j++) {
+                    object->position(lineSegmentPoints[i].getX(), lineSegmentPoints[i].getY(), lineSegmentPoints[i].getZ());
+                    object->position(lineSegmentPoints[j].getX(), lineSegmentPoints[j].getY(), lineSegmentPoints[j].getZ());
+                }
+            }
+        }
+    }
+}
+
+void OgreSceneObjectFactory::specifyBoundingVolumeTrianglesForSphere(Ogre::ManualObject* object, const dcollide::BoundingSphere* boundingSphere) {
+    if (!boundingSphere) {
+        throw dcollide::NullPointerException("const dcollide::BoundingSphere* boundingSphere");
+    }
+
+    // AB: we use the defaul precision currently.
+    //     therefore the bounding sphere does not look a lot like a bounding
+    //     sphere, but it takes much less memory and processing power.
+    //     feel free to adjust, if you want a nicer sphere
+    //     (i.e. add a precision parameter here)
+    // OH: A precision parameter around 0.4 is very well even for big spheres,
+    //     but unfortunately the rendering gets very slow acording to the huge
+    //     amount of triangles.
+    const static dcollide::Mesh* mesh = 0;
+    if (mesh == 0) {
+        dcollide::Sphere sphere(1);
+
+#ifdef __GNUC__
+#warning FIXME: delete on destruction
+#endif
+        mesh = sphere.getMesh()->cloneMesh();
+    }
+
+    const static std::vector<dcollide::Triangle*>& triangles = mesh->getTriangles();
+
+    for (std::vector<dcollide::Triangle*>::const_iterator it = triangles.begin(); it != triangles.end(); ++it) {
+        const dcollide::Vertex* v;
+        const dcollide::Vector3 normal = (*it)->getNormalVector();
+        for (int i = 0; i < 3; i++) {
+            v = (*it)->getVertices()[i];
+            dcollide::Vector3 pos = boundingSphere->getCenterVector() +
+                                    (v->getPosition() *
+                                     boundingSphere->getRadius());
+
+            object->position(pos.getX(), pos.getY(), pos.getZ());
+            object->normal(normal.getX(), normal.getY(), normal.getZ());
+        }
+    }
+
+    dcollide::Vector3 bvMin = boundingSphere->getSurroundingAabbMin();
+    dcollide::Vector3 bvMax = boundingSphere->getSurroundingAabbMax();
+    Ogre::Vector3 min(bvMin[0], bvMin[1], bvMin[2]);
+    Ogre::Vector3 max(bvMax[0], bvMax[1], bvMax[2]);
+    Ogre::AxisAlignedBox aabb(min, max);
+    object->setBoundingBox(aabb);
+}
+
+void OgreSceneObjectFactory::specifyHierarchicalGrid(Ogre::ManualObject* object,
+        const dcollide::HierarchicalGrid* grid) {
+    specifyHierarchicalGridPoints(object, grid);
+}
+
+void OgreSceneObjectFactory::specifyHierarchicalGridPoints(Ogre::ManualObject*
+        object, const dcollide::HierarchicalGrid* grid) {
+    const dcollide::Vector3& min = grid->getGridMin();
+    const dcollide::Vector3& max = grid->getGridMax();
+    object->position(min.getX(), min.getY(), min.getZ());
+    object->position(min.getX(), min.getY(), max.getZ());
+    object->position(min.getX(), min.getY(), min.getZ());
+    object->position(min.getX(), max.getY(), min.getZ());
+    object->position(min.getX(), min.getY(), min.getZ());
+    object->position(max.getX(), min.getY(), min.getZ());
+
+    object->position(min.getX(), min.getY(), max.getZ());
+    object->position(min.getX(), max.getY(), max.getZ());
+    object->position(min.getX(), min.getY(), max.getZ());
+    object->position(max.getX(), min.getY(), max.getZ());
+
+    object->position(min.getX(), max.getY(), min.getZ());
+    object->position(min.getX(), max.getY(), max.getZ());
+    object->position(min.getX(), max.getY(), min.getZ());
+    object->position(max.getX(), max.getY(), min.getZ());
+
+    object->position(min.getX(), max.getY(), max.getZ());
+    object->position(max.getX(), max.getY(), max.getZ());
+
+    object->position(max.getX(), min.getY(), min.getZ());
+    object->position(max.getX(), min.getY(), max.getZ());
+    object->position(max.getX(), min.getY(), min.getZ());
+    object->position(max.getX(), max.getY(), min.getZ());
+
+    object->position(max.getX(), min.getY(), max.getZ());
+    object->position(max.getX(), max.getY(), max.getZ());
+
+    object->position(max.getX(), max.getY(), min.getZ());
+    object->position(max.getX(), max.getY(), max.getZ());
+
+    for (std::vector<dcollide::HierarchicalGrid*>::const_iterator it = grid->getChildrenConst().begin(); it != grid->getChildrenConst().end(); ++it) {
+        specifyHierarchicalGridPoints(object, *it);
+    }
+}
+
+void OgreSceneObjectFactory::specifyTrianglesForShape(Ogre::ManualObject* object,
+                                                      const dcollide::Shape* shape,
+                                                      const ModelLoader::TextureInformation& textureInformation,
+                                                      bool useTextures) {
+    
+    const dcollide::Mesh* mesh = const_cast<dcollide::Shape*>(shape)->getMesh();
+    const std::vector<dcollide::Triangle*>& triangles = mesh->getTriangles();
+    const std::vector<dcollide::Vertex*>& vertices = mesh->getVertices();
+
+    std::map<const dcollide::Vertex*, int> vertex2Index;
+    int index = 0;
+    for (std::vector<dcollide::Vertex*>::const_iterator it = vertices.begin(); it != vertices.end(); ++it) {
+        vertex2Index.insert(std::make_pair(*it, index));
+        index++;
+    }
+
+    const std::vector<dcollide::Vector3>& texels = textureInformation.getTexels();
+
+    // actual "rendering" code
+    {
+        int index = 0;
+        int triangle = 0;
+        for (std::vector<dcollide::Triangle*>::const_iterator it = triangles.begin(); it != triangles.end(); ++it) {
+            const dcollide::Vertex* v;
+            const dcollide::Vector3* pos;
+            const dcollide::Vector3* normal;
+
+            for (int i = 0; i < 3; i++) {
+
+                v = (*it)->getVertices()[i];
+
+                pos = &(v->getPosition());
+                normal = (*it)->getNormals()[i];
+
+                object->position(pos->getX(), pos->getY(), pos->getZ());
+                object->normal(normal->getX(), normal->getY(), normal->getZ());
+
+                if (useTextures && textureInformation.isTextured()) {
+                    if (textureInformation.getTexelSharing()) {
+                        std::map<const dcollide::Vertex*, int>::const_iterator vertexIndexIt = vertex2Index.find(v);
+                        if (vertexIndexIt == vertex2Index.end()) {
+                            throw dcollide::Exception("Triangle vertex not in the getVertices() of the mesh");
+                        }
+                        int vertexIndex = (*vertexIndexIt).second;
+                        if (textureInformation.isTextured()) {
+                            dcollide::Vector3 v = texels[vertexIndex];
+                            object->textureCoord(v[0], v[1], v[2]);
+                        }
+                    } else {
+                        dcollide::Vector3 v = texels[index];
+                        object->textureCoord(v[0], v[1], v[2]);
+                    }
+                }
+
+                index++;
+            }
+
+            triangle++;
+        }
+    }
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/axisobject.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/axisobject.cpp (revision 1189)
+++ /d-collide/tags/1.0.0/testapp/axisobject.cpp (revision 1189)
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-users@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,          *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+// Code taken fromhttp://www.ogre3d.org/wiki/index.php/ManualObject_AxisObject
+// and adapted to make it compile
+//
+//  Filename : AxisObject.cpp
+
+#include "axisobject.h"
+#include "Ogre.h"
+#include "OgreMaterial.h"
+
+using namespace Ogre;
+
+void AxisObject::addBox(ManualObject* obj, Vector3 dim, Vector3 pos, ColourValue color, short boxMask) {
+    if (!obj) {
+        return;
+    }
+
+    obj->begin("Axis", Ogre::RenderOperation::OT_TRIANGLE_LIST); 
+
+    dim/=2;
+
+    Ogre::Real l = dim.x;
+    Ogre::Real h = dim.y;
+    Ogre::Real w = dim.z;
+    
+    obj->position(Ogre::Vector3(-l, h, w) + pos);
+    obj->colour(color);
+    obj->position(Ogre::Vector3(-l, -h, w) + pos);
+    obj->colour(color);
+    obj->position(Ogre::Vector3(l, -h, w) + pos);
+    obj->colour(color);
+    obj->position(Ogre::Vector3(l, h, w) + pos);
+
+    obj->position(Ogre::Vector3(-l, h, -w) + pos);
+    obj->colour(color);
+    obj->position(Ogre::Vector3(-l, -h, -w) + pos); 
+    obj->colour(color);
+    obj->position(Ogre::Vector3(l, -h, -w) + pos);
+    obj->colour(color);
+    obj->position(Ogre::Vector3(l, h, -w) + pos);
+
+    // front back
+    if (boxMask & BOX_FRONT) {
+        obj->quad(0, 1, 2, 3);
+    }
+    if (boxMask & BOX_BACK) {
+        obj->quad(7, 6, 5, 4);
+    }
+
+    // top bottom
+    if (boxMask & BOX_TOP) {
+        obj->quad(0, 3, 7, 4);
+    }
+    if (boxMask & BOX_BOT) {
+        obj->quad(2, 1, 5, 6);
+    }
+
+    // end caps
+    if (boxMask & BOX_RIGHT) {
+        obj->quad(1, 0, 4, 5);
+    }
+    if (boxMask & BOX_LEFT) {
+        obj->quad(3, 2, 6, 7);
+    }
+
+    obj->end();
+}
+
+void AxisObject::addMaterial(const Ogre::String& mat, Ogre::ColourValue& clr, Ogre::SceneBlendType sbt) {
+    static int init=false;
+    if (init) {
+        return;
+    } else {
+        init=true;
+    }
+
+    Ogre::MaterialPtr matptr = Ogre::MaterialManager::getSingleton().create(mat, "General"); 
+    matptr->setReceiveShadows(false); 
+    matptr->getTechnique(0)->setLightingEnabled(true);
+    matptr->getTechnique(0)->getPass(0)->setDiffuse(clr); 
+    matptr->getTechnique(0)->getPass(0)->setAmbient(clr); 
+    matptr->getTechnique(0)->getPass(0)->setSelfIllumination(clr); 
+    matptr->getTechnique(0)->getPass(0)->setSceneBlending(sbt);
+    matptr->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+    matptr->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_DIFFUSE);
+}
+
+Ogre::ManualObject* AxisObject::createAxis(Ogre::SceneManager* scene, const Ogre::String& name, Ogre::Real scale) {
+    const Ogre::String axisMaterialName = "Axis";
+    Ogre::ColourValue colour(1,1,1,.75);
+    addMaterial(axisMaterialName, colour, Ogre::SBT_TRANSPARENT_ALPHA);
+
+    Ogre::ManualObject* axis    = scene->createManualObject(name); 
+
+    Ogre::Real len=scale;
+    Ogre::Real scl=len*.1;
+    Ogre::Real loc=len/2+scl/2;
+    Ogre::Real fade=.5;
+    Ogre::Real solid=.8;
+    
+    addBox(axis, Vector3(len, scl, scl), Vector3(loc,0,0), ColourValue(0, 0, solid, solid), (BOX_ALL & ~BOX_RIGHT)); 
+    addBox(axis, Vector3(len, scl, scl), Vector3(-loc,0,0), ColourValue(0, 0, fade, fade), (BOX_ALL & ~BOX_LEFT)); 
+
+    addBox(axis, Vector3(scl, len, scl), Vector3(0,loc,0), ColourValue(0, solid, 0, solid), (BOX_ALL & ~BOX_BOT)); 
+    addBox(axis, Vector3(scl, len, scl), Vector3(0,-loc,0), ColourValue(0, fade, 0, fade), (BOX_ALL & ~BOX_TOP)); 
+
+    addBox(axis, Vector3(scl, scl, len), Vector3(0,0,loc), ColourValue(solid, 0, 0, solid), (BOX_ALL & ~BOX_BACK)); 
+    addBox(axis, Vector3(scl, scl, len), Vector3(0,0,-loc), ColourValue(fade, 0, 0, fade), (BOX_ALL & ~BOX_FRONT)); 
+
+    axis->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
+
+    return axis;
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/testappcommandline.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/testappcommandline.h (revision 1272)
+++ /d-collide/tags/1.0.0/testapp/testappcommandline.h (revision 1272)
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_TESTAPPCOMMANDLINE_H
+#define DCOLLIDE_TESTAPPCOMMANDLINE_H
+
+#include "commandlineparser.h"
+
+class TestApp;
+
+class TestAppCommandLine : public CommandLineParser {
+    public:
+        TestAppCommandLine();
+        virtual ~TestAppCommandLine();
+
+        bool parseAndApplyArgs(int argc, char** argv, TestApp* testapp);
+        bool applyArgsAfterInitialization(TestApp* testapp);
+};
+
+#endif
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/CMakeLists.txt
===================================================================
--- /d-collide/tags/1.0.0/testapp/CMakeLists.txt (revision 3359)
+++ /d-collide/tags/1.0.0/testapp/CMakeLists.txt (revision 3359)
@@ -0,0 +1,168 @@
+find_package(OGRE)
+
+# check whether the modelloader library has been built with lib3ds support
+get_target_property(LIB3DS_SUPPORT modelloader HAVE_LIB3DS)
+
+set (BUILD_TESTAPP false)
+if (OGRE_FOUND AND LIB3DS_SUPPORT)
+    set (BUILD_TESTAPP true)
+else (OGRE_FOUND AND LIB3DS_SUPPORT)
+    if (NOT OGRE_FOUND)
+        message(STATUS "Ogre not found. Cannot compile test application.")
+    endif (NOT OGRE_FOUND)
+    if (NOT LIB3DS_SUPPORT)
+        message(STATUS "modelloader lacks lib3ds support. Cannot compile test application.")
+    endif (NOT LIB3DS_SUPPORT)
+endif (OGRE_FOUND AND LIB3DS_SUPPORT)
+
+
+if (BUILD_TESTAPP)
+    include_directories(${OGRE_INCLUDE_DIRS})
+    link_directories(${OGRE_LIBRARY_DIRS})
+    link_directories(${CMAKE_BINARY_DIR}/ode)
+    add_definitions(${OGRE_CFLAGS_OTHERS})
+
+#if (FALSE)
+    # AB: make sure our local ODE is the _first_ include dir
+    #     -> otherwise a path which contains an already installed ODE might be
+    #        catched before and cause some harm
+    include_directories(BEFORE ${CMAKE_SOURCE_DIR}/ode/include)
+    include_directories(BEFORE ${CMAKE_BINARY_DIR}/ode/include)
+    set(ODE_LIBRARY myode)
+#else (FALSE)
+#find_package(ODE)
+#include_directories(${ODE_INCLUDE_DIRS})
+#endif (FALSE)
+
+    set(testapp_SRCS
+
+        testapp.cpp
+        inputhandler.cpp
+        inputlistener.cpp
+        ogresceneobjectfactory.cpp
+        ogrematerials.cpp
+        myobjectnode.cpp
+        mydeformableobjectnode.cpp
+        uiaction.cpp
+        gui.cpp
+        axisobject.cpp
+        framehistory.cpp
+        commandlineparser.cpp
+        testappcommandline.cpp
+
+        odewrapper.cpp
+
+        scenes/scenebase.cpp
+        scenes/physicsscenebase.cpp
+        scenes/scenemanager.cpp
+        
+        scenes/deformable/deforming.cpp
+        scenes/deformable/deformablescene.cpp
+        scenes/deformable/deformablescenecollisions.cpp
+        scenes/deformable/deformablescenespheres.cpp
+        scenes/deformable/spherecloth.cpp
+
+        scenes/general/devtest.cpp
+        scenes/general/collisionstopscene.cpp
+        scenes/general/dcollidescene.cpp
+        scenes/general/penetrationdepthscene.cpp
+        scenes/general/specificationscene.cpp
+
+        scenes/physics/boxstackscene.cpp
+        scenes/physics/clothbox.cpp
+        scenes/physics/rotatingcloth.cpp
+        scenes/physics/collisionresponse.cpp
+        scenes/physics/rampscene.cpp
+        scenes/physics/snookerscene.cpp
+        scenes/physics/wallscene.cpp
+        scenes/physics/shakescene.cpp
+        scenes/physics/dominoday.cpp
+        scenes/physics/marblerun.cpp
+        scenes/physics/hangingclothscene.cpp
+        
+        scenes/rigid/manymovingboxes.cpp
+        scenes/rigid/movingbunny.cpp
+        scenes/rigid/tworigidhelicopters.cpp
+        scenes/rigid/tworigidhelicoptersingrid.cpp
+
+        scenes/benchmark/mixed.cpp
+        scenes/benchmark/rigid.cpp
+        scenes/benchmark/deformable.cpp
+
+        modelloader/modelloader3ds.cpp
+        modelloader/modelloaderply.cpp
+    )
+
+    if (APPLE)
+        set (maxosxFlags "MACOSX_BUNDLE")
+
+        set (MACOSX_BUNDLE_BUNDLE_NAME "TestApp")
+        set (MACOSX_BUNDLE_INFO_STRING "D-Collide Test Application")
+        set (MACOSX_BUNDLE_ICON_FILE "TestApp.icns")
+        set (MACOSX_BUNDLE_GUI_IDENTIFIER "d-collide.TestApp")
+
+        # TODO: set bundle properties
+        #set (MACOSX_BUNDLE_LONG_VERSION_STRING "")
+        #set (MACOSX_BUNDLE_COPYRIGHT "")
+
+        # copy resources into the bundle
+        set (BUNDLE_RESOURCES_PATH "${CMAKE_BINARY_DIR}/testapp/TestApp.app/Contents/Resources")
+        set (_RESOURCE_SOURCE "${CMAKE_SOURCE_DIR}/testapp/resources")
+
+        # for Mac OS X we need to copy ALL resources into the bundle
+        # as we won't install anything to /usr/share (or the like)
+
+        file(MAKE_DIRECTORY "${BUNDLE_RESOURCES_PATH}")
+
+        foreach(_EXT "imageset" "xsd" "scheme" "tga" "JPG" "ply" "3ds" "mesh" "material")
+            file(GLOB_RECURSE _RESOURCES RELATIVE "${_RESOURCE_SOURCE}"
+                 "${_RESOURCE_SOURCE}/*.${_EXT}"
+            )
+            set (BUNDLE_RESOURCES "${_RESOURCES}" "${BUNDLE_RESOURCES}")
+        endforeach(_EXT)
+
+        foreach (_RESOURCE ${BUNDLE_RESOURCES})
+            configure_file("${_RESOURCE_SOURCE}/${_RESOURCE}"
+                           "${BUNDLE_RESOURCES_PATH}/${_RESOURCE}" COPYONLY)
+        endforeach(_RESOURCE)
+
+        configure_file("${CMAKE_SOURCE_DIR}/testapp/resources/d-collide.icns"
+                       "${BUNDLE_RESOURCES_PATH}/TestApp.icns" COPYONLY)
+    endif (APPLE)
+
+    if (WIN32)
+        set (windowsResourceFile "resources/icon.rc")
+    endif (WIN32)
+
+    add_executable(testapp ${maxosxFlags} main.cpp ${testapp_SRCS} ${windowsResourceFile})
+
+    target_link_libraries(testapp
+        modelloader
+        ${ODE_LIBRARY}
+        dcollide-static
+        ${OGRE_LIBRARIES})
+
+    install(TARGETS testapp DESTINATION bin)
+    install(DIRECTORY resources/cegui-skin resources/models resources/textures
+            DESTINATION resources
+            PATTERN ".svn" EXCLUDE)
+
+endif (BUILD_TESTAPP)
+
+set(DCOLLIDE_TESTAPP_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
+set(DCOLLIDE_TESTAPP_SOURCE_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})
+
+# AB: note: we create the config file even if ogre was NOT found.
+#           this way we can always assume that it exists.
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dcollide-config_testapp.h.cmake
+    ${CMAKE_CURRENT_BINARY_DIR}/dcollide-config_testapp.h)
+
+# make sure dcollide-config_testapp.h will always be found
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+
+# vim: et sw=4 ts=4
Index: /d-collide/tags/1.0.0/testapp/inputhandler.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/inputhandler.cpp (revision 2391)
+++ /d-collide/tags/1.0.0/testapp/inputhandler.cpp (revision 2391)
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "inputhandler.h"
+#include "inputlistener.h"
+#include "uiaction.h"
+#include "testapp.h"
+#include "scenes/scenebase.h"
+#include "dcollide-config_testapp.h"
+
+#include <OgreCamera.h>
+
+#include <d-collide/debug.h>
+#include <d-collide/world.h>
+
+#include <iostream>
+
+/*!
+ * Construct an OIS based event handler system.
+ */
+InputHandler::InputHandler(std::size_t winHandle) {
+    mCamera = 0;
+    mScene = 0;
+    mActionCollection = new UiActionCollection();
+    mInputListener = new InputListener(winHandle, this);
+
+    mWantQuit = false;
+
+    mShowBoundingVolumesAction = 0;
+    mShowProxiesAction = 0;
+    mPauseAction = 0;
+    mUseCollisionCacheAction = 0;
+    mShowHierarchicalGridAction = 0;
+    mUseThreads = 0;
+    mWantSingleStep = false;
+}
+
+InputHandler::~InputHandler() {
+    delete mInputListener;
+    delete mActionCollection;
+}
+
+UiActionCollection* InputHandler::getActionCollection() const {
+    return mActionCollection;
+}
+
+/*!
+ * Initialize \ref UiAction objects - in particular this method requires that
+ * CEGUI is set up properly, so that buttons can be added.
+ */
+void InputHandler::initActions() {
+    mShowProxiesAction = new UiToggleAction(getActionCollection(), "ShowProxies");
+    mShowProxiesAction->addToggleCallback(&InputHandler::showAllProxies, this);
+    mShowProxiesAction->setOisShortcut(OIS::KC_S);
+    mShowProxiesAction->setChecked(true);
+
+    mShowBoundingVolumesAction = new UiToggleAction(getActionCollection(), "ShowBoundingVolumes");
+    mShowBoundingVolumesAction->addToggleCallback(&InputHandler::showAllBoundingVolumes, this);
+    mShowBoundingVolumesAction->setOisShortcut(OIS::KC_B);
+
+    mPauseAction = new UiToggleAction(getActionCollection(), "Pause");
+    mPauseAction->setOisShortcut(OIS::KC_P);
+
+    new UiToggleAction(getActionCollection(), "PauseMovements");
+
+    mUseCollisionCacheAction = new UiToggleAction(getActionCollection(), "UseCollisionCache");
+    mUseCollisionCacheAction->addToggleCallback(&InputHandler::setUseCollisionCache, this);
+    mUseCollisionCacheAction->setOisShortcut(OIS::KC_C);
+
+    mShowHierarchicalGridAction = new UiToggleAction(getActionCollection(),
+        "ShowOctree");
+    mShowHierarchicalGridAction->addToggleCallback(
+        &InputHandler::setShowHierarchicalGrid, this);
+    mShowHierarchicalGridAction->setOisShortcut(OIS::KC_O);
+
+    mUseThreads = new UiToggleAction(getActionCollection(), "UseThreads");
+    mUseThreads->setOisShortcut(OIS::KC_T);
+
+    new UiToggleAction(getActionCollection(), "UsePipelining");
+
+    UiToggleAction* narrowResults = new UiToggleAction(getActionCollection(), "NarrowPhaseResults");
+    narrowResults->addToggleCallback(&InputHandler::setShowNarrowPhaseResults, this);
+    narrowResults->setOisShortcut(OIS::KC_N);
+
+    UiToggleAction* skipNarrowPhase = new UiToggleAction(getActionCollection(), "SkipNarrowPhase");
+    skipNarrowPhase->setOisShortcut(OIS::KC_A); // N_a_rrowPhase
+
+    UiToggleAction* skipMiddlePhase = new UiToggleAction(getActionCollection(), "SkipMiddlePhase");
+    skipMiddlePhase->setOisShortcut(OIS::KC_M);
+
+    UiPushButtonAction* stepButton = new UiPushButtonAction(getActionCollection(), "StepButton");
+    stepButton->addActionCallback(&InputHandler::doSingleStep, this);
+}
+
+/*!
+ * Called once per frame - triggers OIS to update the input device states.
+ */
+void InputHandler::captureInput(float timeSinceLastFrame) {
+    if (mInputListener) {
+        mInputListener->captureInput(timeSinceLastFrame);
+    }
+}
+
+/*!
+ * Request to quit the application. The request will be processed once the event
+ * loop is re-entered.
+ */
+void InputHandler::queueQuit() {
+    mWantQuit = true;
+}
+
+/*!
+ * \return TRUE if the user indicated that he wants to quit the application.
+ * Otherwise FALSE.
+ */
+bool InputHandler::getWantQuit() const {
+    return mWantQuit;
+}
+
+/*!
+ * Should be called when the window that this input handler is assigned to has
+ * been closed. From that point on, no further input is being processed, \ref
+ * captureInput is a noop.
+ *
+ * This is important on linux, to ensure proper destruction: the OIS objects
+ * must be deleted before the window is destroyed.
+ */
+void InputHandler::notifyWindowClosed() {
+    delete mInputListener;
+    mInputListener = 0;
+}
+
+void InputHandler::setWindowSize(unsigned int width, unsigned int height) {
+    if (mInputListener) {
+        mInputListener->setWindowSize(width, height);
+    }
+}
+
+void InputHandler::setCamera(Ogre::Camera* camera) {
+    mCamera = camera;
+}
+
+void InputHandler::setScene(SceneBase* scene) {
+    mScene = scene;
+}
+
+void InputHandler::setTestApp(TestApp* testapp) {
+    mTestApp = testapp;
+}
+
+void InputHandler::showAllBoundingVolumes(bool show) {
+    if (mScene) {
+        mScene->setAllBoundingVolumesVisible(show);
+    }
+}
+
+void InputHandler::showAllProxies(bool show) {
+    if (mScene) {
+        mScene->setAllProxiesVisible(show);
+    }
+}
+
+bool InputHandler::getPause() const {
+    return isChecked("Pause");
+}
+
+bool InputHandler::getUseCollisionCache() const {
+    if (!mScene || !mScene->getCollisionWorld()) {
+        return false;
+    }
+    return mScene->getCollisionWorld()->getUseCollisionCaching();
+}
+
+void InputHandler::setUseCollisionCache(bool c) {
+    if (mScene && mScene->getCollisionWorld()) {
+        mScene->getCollisionWorld()->setUseCollisionCaching(c);
+    }
+}
+
+void InputHandler::setShowHierarchicalGrid(bool show) {
+    if (mScene) {
+        mScene->setHierarchicalGridVisible(show);
+    }
+}
+
+void InputHandler::setShowNarrowPhaseResults(bool show) {
+    if (mScene) {
+        mScene->setNarrowPhaseResultsVisible(show);
+    }
+}
+
+bool InputHandler::getUseThreads() const {
+    if (mUseThreads) {
+        return mUseThreads->isChecked();
+    }
+    return true;
+}
+
+/*!
+ * See \ref UiActionCollection::setChecked
+ */
+void InputHandler::setChecked(const std::string& actionName, bool c) {
+    mActionCollection->setChecked(actionName, c);
+}
+
+/*!
+ * \return UiActionCollection::isChecked
+ */
+bool InputHandler::isChecked(const std::string& actionName) const {
+    return mActionCollection->isChecked(actionName);
+}
+
+/*!
+ * Force activation of all callbacks of the \ref UiToggleAction objects. See
+ * \ref UiToggleAction::forceToggleCallbackActivation.
+ *
+ * This should be called whenever the current scene has been changed completely,
+ * so that the current values of \ref UiToggleAction::isChecked of all toggle
+ * objects can be applied to that scene.
+ */
+void InputHandler::forceToggleCallbackActivation() {
+    const std::list<UiAction*>& actions = mActionCollection->getActions();
+    for (std::list<UiAction*>::const_iterator it = actions.begin(); it != actions.end(); ++it) {
+        UiToggleAction* toggle = dynamic_cast<UiToggleAction*>(*it);
+        if (toggle) {
+            toggle->forceToggleCallbackActivation();
+        }
+    }
+}
+
+
+void InputHandler::changeCurrentScene(const std::string& sceneId) {
+    if (mTestApp) {
+        mTestApp->changeCurrentScene(sceneId);
+    }
+}
+
+void InputHandler::setCameraDefaultView(CameraSetup view){
+    switch (view) {
+        case CAMERA_SETUP_VIEW_FRONT: {
+            mCamera->setPosition(Ogre::Vector3(200, 0, 0));
+            mCamera->lookAt(Ogre::Vector3(0, 0, 0));
+        } break;
+        case CAMERA_SETUP_VIEW_SIDE: {
+            mCamera->setPosition(Ogre::Vector3(0.0f, 200.0f, 0.0f));
+            mCamera->lookAt(Ogre::Vector3(0, 0, 0));
+        } break;
+        case CAMERA_SETUP_VIEW_TOP: {
+            mCamera->setPosition(Ogre::Vector3(0, 0, 200));
+            mCamera->lookAt(Ogre::Vector3(0, 0, 0));
+        } break;
+        case CAMERA_SETUP_VIEW_ISOMETRIC: {
+            mCamera->setPosition(Ogre::Vector3(200, 200, 200));
+            mCamera->lookAt(Ogre::Vector3(0, 0, 0));
+        } break;
+    }
+
+}
+
+void InputHandler::doSingleStep() {
+    setSingleStep(true);
+}
+
+void InputHandler::setSingleStep(bool s) {
+    mWantSingleStep = s;
+}
+
+bool InputHandler::getSingleStep() const {
+    return mWantSingleStep;
+}
+
+// TODO: windowResize() etc.
+// -> mouse clipping area
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.cpp (revision 2684)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.cpp (revision 2684)
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "deformablescene.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+
+#include <d-collide/debug.h>
+#include <d-collide/world.h>
+#include <d-collide/shapes/shapes.h>
+
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+DeformableScene::DeformableScene(Ogre::Root* root)
+        : SceneBase(root) {
+}
+
+DeformableScene::~DeformableScene() {
+}
+
+dcollide::Vector3 DeformableScene::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+void DeformableScene::addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const {
+    std::list<dcollide::DeformableAlgorithmType> algorithm;
+    algorithm.push_back(dcollide::DEFORMABLE_TYPE_SURFACE_HIERARCHY);
+    parameters.setDeformableAlgorithms(algorithm);
+}
+
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ **/
+bool DeformableScene::initializeScene() {
+
+
+    //bunny.ply , bunny_lower_res2.ply , horse.ply , dragon_vrip_res4.ply , dragon_vrip_res3.ply , dragon_stand/dragonStandRight_0.ply
+    MyObjectNode* bigModelDeformable = createPlyModel("bunny_lower_res2.ply",
+            (dcollide::ProxyTypes) (dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE),
+             800.0f);
+
+    bigModelDeformable->translate(dcollide::Vector3(0.0, -80.0, -120.0));
+    bigModelDeformable->rotate(15.0, 1.0, 0.0, 0.0);
+
+    if (bigModelDeformable) {
+        addTopLevelObject(bigModelDeformable);
+        //bigModelDeformable->rotate();
+    }
+
+
+    std::cout << dc_funcinfo << "done" << std::endl;
+    return true;
+}
+
+/*!
+ * Start a new frame of the scene, i.e. moves all movable object by a bit.
+ *
+ * This is NOT necessarily equal to a graphic frame! In fact the scene frames
+ * should depend on time only, not on CPU or GPU power as the graphic frames do.
+ */
+void DeformableScene::startNextSceneFrame() {
+
+
+
+}
+
+std::string DeformableScene::getSceneDescription() const {
+    return "This scene is a performance test for the SurfaceHierarchy algorithm.\nThe bunny consists of ~16.000 triangles";
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.h (revision 2819)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.h (revision 2819)
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_DEFORMING_H
+#define DCOLLIDE_DEFORMING_H
+
+#include "scenes/scenebase.h"
+
+#include <d-collide/worldparameters.h>
+#include <d-collide/real.h>
+
+#include <vector>
+#include <string>
+#include <list>
+
+namespace dcollide {
+    class World;
+    class Proxy;
+    class Mesh;
+    class WorldCollisions;
+}
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+class MyDeformableObjectNode;
+
+class Deforming : public SceneBase {
+    public:
+        Deforming(Ogre::Root* root);
+        virtual ~Deforming();
+
+        virtual std::string getSceneDescription() const;
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+        virtual void addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const;
+
+    private:
+        dcollide::real mAmplitude;
+        dcollide::real mPeriod;
+        dcollide::real mCircleAngle;
+        dcollide::real mRadius;
+        dcollide::real mAngle;
+
+        MyDeformableObjectNode* mDeformingBox;
+        MyDeformableObjectNode* mCloth;
+        MyDeformableObjectNode* mSelfCollidingCloth;
+
+        dcollide::Vector3 middlePoint;
+
+        std::vector<dcollide::Vector3> mDeformVector;
+        std::vector<dcollide::Vector3> mClothDeformVector;
+        std::vector<dcollide::Vector3> mSelfCollidingClothDeformVector;
+
+        unsigned int mStep;
+};
+
+#endif
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.cpp (revision 3029)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.cpp (revision 3029)
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "spherecloth.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+
+#include <modelloader/loaderdummy.h>
+
+#include <d-collide/debug.h>
+#include <d-collide/shapes/mesh.h>
+#include <d-collide/shapes/sphere.h>
+#include <d-collide/shapes/box.h>
+
+using namespace dcollide;
+
+SphereCloth::SphereCloth(Ogre::Root* root)
+        : PhysicsSceneBase(root) {
+}
+
+SphereCloth::~SphereCloth() {
+}
+
+dcollide::Vector3 SphereCloth::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+void SphereCloth::addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const {
+    std::list<dcollide::DeformableAlgorithmType> algorithm;
+    //algorithm.push_back(dcollide::DEFORMABLE_TYPE_BV_HIERARCHY);
+    //algorithm.push_back(dcollide::DEFORMABLE_TYPE_SPATIAL_HASH);
+    algorithm.push_back(dcollide::DEFORMABLE_TYPE_SURFACE_HIERARCHY);
+    parameters.setDeformableAlgorithms(algorithm);
+}
+
+Mesh* SphereCloth::createClothMesh(real sidelength, int xtiles, int ytiles) {
+
+    //Step one: Build vertices of the cloth
+    //Vertices will be arrangend in a regular grid with a total sidelength
+    //given by the parameter.
+
+    std::vector<dcollide::Vertex*>   vertices;
+
+    //Center the cloth in local coordinates
+    real xoffset = -(xtiles * sidelength / 2 );
+    real yoffset = -(ytiles * sidelength / 2 );
+    Vector3 position(xoffset,yoffset,0);
+
+    real step = sidelength;
+
+    for(int y = 0; y < ytiles; y++ ) {
+        for(int x = 0; x < xtiles; x++) {
+            //Add vertice
+            position.set(x*step + xoffset,y*step + yoffset,0);
+            vertices.push_back(new dcollide::Vertex(position));
+        }
+    }
+
+    //Step two: build triangles of the cloth
+    std::vector<dcollide::Triangle*> triangles;
+
+    for(int y = 0; y < ytiles - 1; y++ ) {
+        for(int x = 0; x < xtiles - 1; x++) {
+            //Build first triangle
+            triangles.push_back(
+                new Triangle(vertices[ gridCoord(x+1,y  ,xtiles) ],
+                             vertices[ gridCoord(x  ,y  ,xtiles) ],
+                             vertices[ gridCoord(x  ,y+1,xtiles) ]));
+
+            //Build second triangle
+            triangles.push_back(
+                new Triangle(vertices[ gridCoord(x+1,y+1,xtiles) ],
+                             vertices[ gridCoord(x+1,y  ,xtiles) ],
+                             vertices[ gridCoord(x  ,y+1,xtiles) ]));
+        }
+    }
+
+    return new Mesh(vertices, triangles);
+}
+
+int SphereCloth::gridCoord(int x, int y, int resolution) {
+    return y * resolution + x;
+}
+bool SphereCloth::initializeScene() {
+    //Define the physic attributes of our scene
+    dWorldSetGravity(getOdeWorld(), 0, 0, -7.5);
+   mPhysicsSimStepsize = 0.03;
+   mLinearDampingFactor = 0.001;
+   mAngularDampingFactor = 0.005;
+
+    mCloth = new MyDeformableObjectNode(getCollisionWorld(),
+                                                   createClothMesh(3,15,40),
+                                                   dcollide::PROXYTYPE_DEFORMABLE |
+                                                   dcollide::PROXYTYPE_SELFCOLLIDABLE,
+                                                   false);
+
+    mCloth->createPhysicsBody(mOdeWorld, 25);
+    //rotate cloth so that the faces look down
+    //FIXME this causes the cloth to crumble (See ticket #368)
+    //      GJ: as a workaround, i directly changed the triangles.
+    //mCloth->rotate(180, 1,0,0);
+    addTopLevelObject(mCloth);
+    mCloth->translate(0, -20, 0);
+
+    MyObjectNode* environment = new MyObjectNode(getCollisionWorld(), 0, dcollide::PROXYTYPE_FIXED);
+    for(int x = 0; x < 15; x++) {
+            int y = 0;
+            MyObjectNode* box = new MyObjectNode (getCollisionWorld(),
+                        new dcollide::Box(6.0, 6.0, 6.0),
+                        //new dcollide::Sphere(3),
+                        dcollide::PROXYTYPE_FIXED,true, false);
+            box->setPosition(x*6.0-25,y*6.0-25,-100);
+            environment->addChild(box);
+    }
+    addTopLevelObject(environment);
+
+    const_cast<ModelLoader::TextureInformation&> (mCloth
+                        ->getTextureInformation()).setTransparent(0.5);
+    return true;
+}
+
+void SphereCloth::startNextSceneFrame() {
+}
+
+void SphereCloth::restart() {
+    removeObject(mCloth);
+
+    mCloth = new MyDeformableObjectNode(getCollisionWorld(),
+                                                   createClothMesh(3,15,40),
+                                                   dcollide::PROXYTYPE_DEFORMABLE |
+                                                   dcollide::PROXYTYPE_SELFCOLLIDABLE,
+                                                   false);
+
+    mCloth->createPhysicsBody(mOdeWorld, 25);
+
+    addTopLevelObject(mCloth);
+    deleteCollisions();
+}
+
+std::string SphereCloth::getSceneDescription() const {
+      return "SelfCollision Test";
+}
+
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.h (revision 2808)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.h (revision 2808)
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_DEFORMABLESCENECOLLISIONS_H
+#define DCOLLIDE_DEFORMABLESCENECOLLISIONS_H
+
+#include "scenes/scenebase.h"
+
+#include <d-collide/world.h>
+#include <d-collide/worldparameters.h>
+
+#include <string>
+#include <list>
+#include <vector>
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+namespace dcollide {
+    class World;
+    class Proxy;
+    class Mesh;
+    class WorldCollisions;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+class MyDeformableObjectNode;
+
+class DeformableSceneCollisions : public SceneBase {
+    public:
+        DeformableSceneCollisions(Ogre::Root* root);
+        virtual ~DeformableSceneCollisions();
+
+        virtual std::string getSceneDescription() const;
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+        virtual void addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const;
+
+    private:
+        dcollide::real mAmplitude;
+        dcollide::real mPeriod;
+        dcollide::real mCircleAngle;
+        MyObjectNode* mBox;
+        MyObjectNode* mStaticCloth;
+        MyDeformableObjectNode* mDeformingCloth;
+        std::vector<dcollide::Vector3> mClothDeformVector;
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.h (revision 2684)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescene.h (revision 2684)
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_DEFORMABLESCENE_H
+#define DCOLLIDE_DEFORMABLESCENE_H
+
+#include "scenes/scenebase.h"
+
+#include <string>
+#include <list>
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+namespace dcollide {
+    class World;
+    class Proxy;
+    class Mesh;
+    class WorldCollisions;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+
+class DeformableScene : public SceneBase {
+    public:
+        DeformableScene(Ogre::Root* root);
+        virtual ~DeformableScene();
+
+        virtual std::string getSceneDescription() const;
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+        virtual void addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const;
+
+    private:
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.h (revision 2893)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/spherecloth.h (revision 2893)
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_SPHERECLOTH_H
+#define DCOLLIDE_SPHERECLOTH_H
+
+#include "scenes/physicsscenebase.h"
+
+#include "mydeformableobjectnode.h"
+#include <d-collide/worldparameters.h>
+#include <d-collide/shapes/mesh.h>
+#include <d-collide/shapes/mesh/triangle.h>
+#include <string>
+#include <list>
+
+namespace dcollide {
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+
+class SphereCloth : public PhysicsSceneBase {
+    public:
+        SphereCloth(Ogre::Root* root);
+        virtual ~SphereCloth();
+
+        virtual std::string getSceneDescription() const;
+
+    protected:
+        virtual void addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const;
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+        virtual void restart();
+
+    private:
+        int gridCoord(int x, int y, int resolution);
+        dcollide::Mesh* createClothMesh(dcollide::real sidelength, int xtiles, int ytiles);
+        MyObjectNode* mSphere;
+        MyObjectNode* mCloth;
+       
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.cpp (revision 2684)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.cpp (revision 2684)
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "deformablescenespheres.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "mydeformableobjectnode.h"
+
+#include <d-collide/debug.h>
+#include <d-collide/worldparameters.h>
+#include <d-collide/shapes/shapes.h>
+#include <d-collide/debugstream.h>
+
+#include <iostream>
+
+#include <modelloader/loaderdummy.h>
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+DeformableSceneSpheres::DeformableSceneSpheres(Ogre::Root* root)
+        : SceneBase(root) {
+}
+
+DeformableSceneSpheres::~DeformableSceneSpheres() {
+}
+
+dcollide::Vector3 DeformableSceneSpheres::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+void DeformableSceneSpheres::addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const {
+    std::list<dcollide::DeformableAlgorithmType> algorithm;
+    algorithm.push_back(dcollide::DEFORMABLE_TYPE_SURFACE_HIERARCHY);
+    parameters.setDeformableAlgorithms(algorithm);
+}
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ **/
+bool DeformableSceneSpheres::initializeScene() {
+
+    ModelLoader::LoaderDummy loader;
+
+    float clothSize = 200.0f;
+    dcollide::Mesh* staticClothMesh = loader.createRectangleSurface(clothSize, clothSize, 5.0f, 5.0f); //20,20
+    if (!staticClothMesh) {
+        dcollide::error() << "Could not create mesh (static)";
+        return false;
+    }
+
+    dcollide::Mesh* deformingClothMesh = loader.createRectangleSurface(clothSize, clothSize, 5.0f, 5.0f); //20,20
+    if (!deformingClothMesh) {
+        dcollide::error() << "Could not create mesh (deforming)";
+        return false;
+    }
+
+    mStaticCloth = new MyObjectNode(getCollisionWorld(), staticClothMesh, dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE, false);
+    mDeformingCloth = new MyDeformableObjectNode(getCollisionWorld(), deformingClothMesh, dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE, false);
+
+    if (mStaticCloth) {
+        addTopLevelObject(mStaticCloth);
+        mStaticCloth->translate(dcollide::Vector3(25.0, -100.0, -300.0));
+    }
+
+    if (mDeformingCloth) {
+        addTopLevelObject(mDeformingCloth);
+        mDeformingCloth->translate(dcollide::Vector3(-225.0, -100.0, -300.0));
+        mDeformingCloth->rotate(-60.0, 1.0, 0.0, 0.0);
+
+        //BoundingVolumes are still misplaced
+    }
+
+    mAmplitude = 5.0;
+    mPeriod = (dcollide::real) 0.2;
+
+    mCircleAngle = 0.0;
+
+    for(unsigned int c=0; c<41; c++){
+
+        for (int i = 0 ; i < 41; i++) {
+
+            dcollide::real x = (dcollide::real) 0.0;
+            dcollide::real y = (dcollide::real) 0.0;
+            dcollide::real z = (dcollide::real) (mAmplitude*(sin(mCircleAngle)));
+
+            dcollide::Vector3 vec(x, y, z);
+            mClothDeformVector.push_back(vec);
+
+        }
+        mCircleAngle = (mCircleAngle + mPeriod);   //%360 ???
+    }
+
+    mDeformingCloth->deform(mClothDeformVector);
+
+    mCircleAngle = 0.0;
+
+    std::cout << dc_funcinfo << "done" << std::endl;
+    return true;
+}
+
+/*!
+ * Start a new frame of the scene, i.e. moves all movable object by a bit.
+ *
+ * This is NOT necessarily equal to a graphic frame! In fact the scene frames
+ * should depend on time only, not on CPU or GPU power as the graphic frames do.
+ */
+void DeformableSceneSpheres::startNextSceneFrame() {
+
+    //mClothDeformVector.clear();
+
+    for(unsigned int c=0; c<41; c++){
+
+        for (int i = 0 ; i < 41; i++) {
+
+            //dcollide::real x = (dcollide::real) 0.0;
+            //dcollide::real y = (dcollide::real) 0.0;
+            //dcollide::real z = (dcollide::real) ( (-1.0) * (mAmplitude*sin((c * mPeriod)+mCircleAngle)) + (mAmplitude*sin((c * mPeriod)+mCircleAngle + mPeriod)));
+
+            mClothDeformVector[c*41+i].setZ((dcollide::real) ( (-1.0) * (mAmplitude*sin((c * mPeriod)+mCircleAngle)) + (mAmplitude*sin((c * mPeriod)+mCircleAngle + mPeriod))));
+
+            //dcollide::Vector3 vec(x, y, z);
+            //mClothDeformVector.push_back(vec);
+
+        }
+    }
+
+    mDeformingCloth->deform(mClothDeformVector);
+
+    mCircleAngle += mPeriod;   //%360 ???
+    if (mCircleAngle >= 360) {
+        mCircleAngle = mPeriod;
+    }
+}
+
+std::string DeformableSceneSpheres::getSceneDescription() const {
+    return "this scene shows the SurfaceHierarchy algorithm\nworking on a flat and regular triangle-grid.";
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.cpp (revision 2819)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deforming.cpp (revision 2819)
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "deforming.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "mydeformableobjectnode.h"
+
+#include <modelloader/loaderdummy.h>
+
+#include <d-collide/debug.h>
+#include <d-collide/math/vector.h>
+#include <d-collide/proxy.h>
+#include <d-collide/world.h>
+#include <d-collide/shapes/mesh/vertex.h>
+#include <d-collide/shapes/shapes.h>
+#include <d-collide/shapes/mesh/vertex.h>
+
+#include <d-collide/detectordeform/spatialhash/spatialhash.h>
+#include <d-collide/detectordeform/detectordeformmanager.h>
+#include <d-collide/worldparameters.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+Deforming::Deforming(Ogre::Root* root) : SceneBase(root) {
+}
+
+Deforming::~Deforming() {
+}
+
+dcollide::Vector3 Deforming::initialWorldDimension() const {
+    return dcollide::Vector3 (2048.0, 2048.0, 2048.0);
+}
+
+void Deforming::addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const {
+    std::list<dcollide::DeformableAlgorithmType> algorithm;
+    algorithm.push_back(dcollide::DEFORMABLE_TYPE_SPATIAL_HASH);
+    //algorithm.push_back(dcollide::DEFORMABLE_TYPE_SURFACE_HIERARCHY);
+    parameters.setDeformableAlgorithms(algorithm);
+}
+
+bool Deforming::initializeScene() {
+    mStep = 0;
+
+    //SelfColliding
+    ModelLoader::LoaderDummy secondLoader;
+    dcollide::Mesh* selfCollidingCloth = secondLoader.createRectangleSurface(60.0, 60.0, 7.0, 11.0);
+    //dcollide::Mesh* selfCollidingCloth = secondLoader.createRectangleSurface(60.0, 5.0, 6.0, 1.0);
+    mSelfCollidingCloth = new MyDeformableObjectNode(getCollisionWorld(),
+                                                     selfCollidingCloth,
+                                                     (dcollide::ProxyTypes) (dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE),
+                                                     false);
+
+    addTopLevelObject(mSelfCollidingCloth);
+    mSelfCollidingCloth->translate(dcollide::Vector3(5.0, -75.0, -250.0));
+    mSelfCollidingCloth->rotate(75.0, 1.0, 0.0, 0.0);
+
+    unsigned int selfColClothNrOfVert = selfCollidingCloth->getVertexCount();
+    std::cout << selfColClothNrOfVert << std::endl;
+    for (unsigned int i=0; i<selfColClothNrOfVert; i++) {
+        dcollide::real x = (dcollide::real) 0.0;
+        dcollide::real y = (dcollide::real) 0.0;
+        dcollide::real z = (dcollide::real) 0.0;
+
+        dcollide::Vector3 vec(x, y, z);
+        mSelfCollidingClothDeformVector.push_back(vec);
+    }
+
+    // Cloth
+    ModelLoader::LoaderDummy firstLoader;
+    dcollide::Mesh* clothMesh = firstLoader.createRectangleSurface(100.0, 100.0, 1.0, 1.0);
+    mCloth = new MyDeformableObjectNode(getCollisionWorld(),
+                                        clothMesh,
+                                        dcollide::PROXYTYPE_DEFORMABLE,
+                                        false);
+
+    addTopLevelObject(mCloth);
+    mCloth->translate(dcollide::Vector3(-125.0, 0.0, -50.0));
+    mCloth->rotate(30.0, 1.0, 0.0, 0.0);
+
+    mAmplitude = 5.0;
+    mPeriod = (dcollide::real) 0.2;
+
+    mCircleAngle = 0.0;
+
+        for (unsigned int c=0; c<101; c++){
+
+            for (int i=0; i<101; i++) {
+
+                dcollide::real x = (dcollide::real) 0.0;
+                dcollide::real y = (dcollide::real) 0.0;
+                dcollide::real z = (dcollide::real) (mAmplitude*(sin(mCircleAngle)));
+
+                dcollide::Vector3 vec(x, y, z);
+                mClothDeformVector.push_back(vec);
+            }
+            mCircleAngle = (mCircleAngle + mPeriod); //%360
+        }
+
+    mCircleAngle = 0.0;
+
+    // Box
+    dcollide::Box box(40.0, 40.0, 40.0);
+    dcollide::Mesh* mesh = box.getMesh()->cloneMesh();
+
+    mDeformingBox = new MyDeformableObjectNode (getCollisionWorld(),
+                                                mesh,
+                                                dcollide::PROXYTYPE_DEFORMABLE);
+
+    addTopLevelObject(mDeformingBox);
+
+    mDeformingBox->translate(dcollide::Vector3(25.0, 0.0, -50.0));
+
+    unsigned int numberOfVertices = mesh->getVertexCount();
+
+    for (unsigned int i=0; i<numberOfVertices; i++){
+        dcollide::real x = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+        dcollide::real y = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+        dcollide::real z = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+
+        dcollide::Vector3 vec(x, y, z);
+        mDeformVector.push_back(vec);
+    }
+
+    mDeformingBox->deform(mDeformVector);
+    mCloth->deform(mClothDeformVector);
+    mSelfCollidingCloth->deform(mSelfCollidingClothDeformVector);
+
+    return true;
+}
+
+void Deforming::startNextSceneFrame() {
+    mStep+=1;
+
+    mRadius = (dcollide::real) -0.2;
+    mAngle = (dcollide::real) 25.0;
+
+    //SelfColliding
+    unsigned int selfColClothNrOfVert = mSelfCollidingCloth->getProxy()->getShape()->getMesh()->getVertexCount();
+    unsigned int middlePointIndex = selfColClothNrOfVert/2;
+
+    std::vector<dcollide::Vertex*> selfCollidingVertexList = mSelfCollidingCloth->getProxy()->getShape()->getMesh()->getVertices();
+    std::vector<dcollide::Vertex*>::iterator iter_SelfVertex = selfCollidingVertexList.begin();
+
+    dcollide::real xCoord = selfCollidingVertexList[middlePointIndex]->getPosition().getX();
+    dcollide::real zCoord = selfCollidingVertexList[middlePointIndex]->getPosition().getZ();
+
+    //dcollide::real xCoord = 0.0;
+    //dcollide::real zCoord = 0.0;
+
+        if(mStep <= 100) {
+            for (unsigned int i=0; i<selfColClothNrOfVert; i++) {
+                std::vector<dcollide::Vertex*> vertices = mSelfCollidingCloth->getProxy()->getShape()->getMesh()->getVertices();
+
+                dcollide::real x = (dcollide::real) ((-1.0)*(xCoord + (mRadius+0.3) * -2 * cos((mAngle-25.0))) + (xCoord + mRadius * -2 * cos(mAngle)));
+                dcollide::real y = (dcollide::real) 0.0;
+                dcollide::real z = (dcollide::real) ((-1.0)*(zCoord + (mRadius+0.3) * -2 * sin((mAngle-25.0))) + (zCoord + mRadius * -2 * sin(mAngle)));
+
+                dcollide::Vector3 vec(x, y, z);
+                mSelfCollidingClothDeformVector[i] = vec;
+
+                mAngle += 25.0;
+                ++iter_SelfVertex;
+            }
+        }
+
+    // Cloth
+    //unsigned int clothNumberOfVertices = mCloth->getProxy()->getShape()->getMesh()->getVertexCount();
+    //unsigned int clothNumberofTriangles = mCloth->getProxy()->getShape()->getMesh()->getTriangleCount();
+    std::vector<dcollide::Vertex*> vertexList = mCloth->getProxy()->getShape()->getMesh()->getVertices();
+    std::vector<dcollide::Vertex*>::iterator iter_vertex = vertexList.begin();
+
+    mClothDeformVector.clear();
+
+    for (unsigned int c=0; c<101; c++){
+        for (int i=0 ; i<101; i++) {
+            dcollide::real x = (dcollide::real) 0.0;
+            dcollide::real y = (dcollide::real) 0.0;
+            dcollide::real z = (dcollide::real) ( (-1.0) * (mAmplitude*sin((c * mPeriod)+mCircleAngle)) + (mAmplitude*sin((c * mPeriod)+mCircleAngle + mPeriod)));
+            //dcollide::real z = (dcollide::real) (5*(sin(mCircleAngle)));
+
+            dcollide::Vector3 vec(x, y, z);
+            //mClothDeformVector[c*101+i] = vec;
+            mClothDeformVector.push_back(vec);
+
+            ++iter_vertex;
+        }
+    }
+
+    mCircleAngle = (mCircleAngle + mPeriod);   //%360;
+
+    // Box
+    dcollide::Mesh* mesh = mDeformingBox->getProxy()->getShape()->getMesh()->cloneMesh();
+    unsigned int numberOfVertices = mesh->getVertexCount();
+
+    for (unsigned int i=0; i<numberOfVertices; i++){
+        dcollide::real x = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+        dcollide::real y = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+        dcollide::real z = (dcollide::real) (sin((dcollide::real)(rand() % 360)));
+
+        dcollide::Vector3 vec(x, y, z);
+        mDeformVector[i] = vec;
+    }
+
+    mCloth->deform(mClothDeformVector);
+    mDeformingBox->deform(mDeformVector);
+
+    if(mStep <= 100){
+        mSelfCollidingCloth->deform(mSelfCollidingClothDeformVector);
+    }
+}
+
+std::string Deforming::getSceneDescription() const {
+    return "A simple scene with deforming objects";
+}
+
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.cpp (revision 2808)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenecollisions.cpp (revision 2808)
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "deformablescenecollisions.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "mydeformableobjectnode.h"
+
+#include <d-collide/debug.h>
+#include <d-collide/worldparameters.h>
+#include <d-collide/shapes/shapes.h>
+#include <d-collide/debugstream.h>
+
+#include <iostream>
+
+#include <modelloader/loaderdummy.h>
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+DeformableSceneCollisions::DeformableSceneCollisions(Ogre::Root* root)
+        : SceneBase(root) {
+}
+
+DeformableSceneCollisions::~DeformableSceneCollisions() {
+}
+
+dcollide::Vector3 DeformableSceneCollisions::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+void DeformableSceneCollisions::addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const {
+    std::list<dcollide::DeformableAlgorithmType> algorithm;
+    algorithm.push_back(dcollide::DEFORMABLE_TYPE_SURFACE_HIERARCHY);
+    parameters.setDeformableAlgorithms(algorithm);
+}
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ **/
+bool DeformableSceneCollisions::initializeScene() {
+
+    ModelLoader::LoaderDummy loader;
+
+    float clothSize = 200.0f;
+    dcollide::Mesh* staticClothMesh = loader.createRectangleSurface(clothSize, clothSize, 5.0f, 5.0f); //20,20
+    if (!staticClothMesh) {
+        dcollide::error() << "Could not create mesh (static)";
+        return false;
+    }
+
+    dcollide::Mesh* deformingClothMesh = loader.createRectangleSurface(clothSize, clothSize, 5.0f, 5.0f); //20,20
+    if (!deformingClothMesh) {
+        dcollide::error() << "Could not create mesh (deforming)";
+        return false;
+    }
+
+    //mStaticCloth = new MyObjectNode(getCollisionWorld(), staticClothMesh, dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE, false);
+    mStaticCloth = new MyObjectNode(getCollisionWorld(), staticClothMesh, dcollide::PROXYTYPE_RIGID, false);
+    mDeformingCloth = new MyDeformableObjectNode(getCollisionWorld(), deformingClothMesh, dcollide::PROXYTYPE_DEFORMABLE | dcollide::PROXYTYPE_SELFCOLLIDABLE, false);
+    
+    mBox = new MyObjectNode(getCollisionWorld(),new dcollide::Box(40,40,40), dcollide::PROXYTYPE_RIGID, false);
+
+    if (mStaticCloth) {
+        mStaticCloth->translate(dcollide::Vector3(-50.0, -50.0, -300.0));
+        mStaticCloth->rotate(-50.0, 1.0, 0.0, 0.0);
+        addTopLevelObject(mStaticCloth);
+    }
+
+    if (mDeformingCloth) {
+        mDeformingCloth->translate(dcollide::Vector3(-150.0, -80.0, -220.0));
+        mDeformingCloth->rotate(60.0, 0.0, 1.0, 0.0);
+        addTopLevelObject(mDeformingCloth);
+    }
+
+    if (mBox) {
+        mBox->translate(-100,0,-330);
+        addTopLevelObject(mBox);
+    }
+
+    mAmplitude = 5.0;
+    mPeriod = (dcollide::real) 0.2;
+
+    mCircleAngle = 0.0;
+
+    for(unsigned int c=0; c<41; c++){
+
+        for (int i = 0 ; i < 41; i++) {
+
+            dcollide::real x = (dcollide::real) 0.0;
+            dcollide::real y = (dcollide::real) 0.0;
+            dcollide::real z = (dcollide::real) (mAmplitude*(sin(mCircleAngle)));
+
+            dcollide::Vector3 vec(x, y, z);
+            mClothDeformVector.push_back(vec);
+
+        }
+        mCircleAngle = (mCircleAngle + mPeriod);   //%360 ???
+    }
+
+    mDeformingCloth->deform(mClothDeformVector);
+
+    mCircleAngle = 0.0;
+
+    std::cout << dc_funcinfo << "done" << std::endl;
+    return true;
+}
+
+/*!
+ * Start a new frame of the scene, i.e. moves all movable object by a bit.
+ *
+ * This is NOT necessarily equal to a graphic frame! In fact the scene frames
+ * should depend on time only, not on CPU or GPU power as the graphic frames do.
+ */
+void DeformableSceneCollisions::startNextSceneFrame() {
+
+    //mClothDeformVector.clear();
+
+    for(unsigned int c=0; c<41; c++){
+
+        for (int i = 0 ; i < 41; i++) {
+
+            //dcollide::real x = (dcollide::real) 0.0;
+            //dcollide::real y = (dcollide::real) 0.0;
+            //dcollide::real z = (dcollide::real) ( (-1.0) * (mAmplitude*sin((c * mPeriod)+mCircleAngle)) + (mAmplitude*sin((c * mPeriod)+mCircleAngle + mPeriod)));
+
+            mClothDeformVector[c*41+i].setZ((dcollide::real) ( (-1.0) * (mAmplitude*sin((c * mPeriod)+mCircleAngle)) + (mAmplitude*sin((c * mPeriod)+mCircleAngle + mPeriod))));
+
+            //dcollide::Vector3 vec(x, y, z);
+            //mClothDeformVector.push_back(vec);
+
+        }
+    }
+
+    mDeformingCloth->deform(mClothDeformVector);
+
+    mCircleAngle += mPeriod;   //%360 ???
+    if (mCircleAngle >= 360) {
+        mCircleAngle = mPeriod;
+    }
+}
+
+std::string DeformableSceneCollisions::getSceneDescription() const {
+    return "this scene shows the SurfaceHierarchy algorithm\nworking on a flat and regular triangle-grid.";
+}
+
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.h (revision 2684)
+++ /d-collide/tags/1.0.0/testapp/scenes/deformable/deformablescenespheres.h (revision 2684)
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_DEFORMABLESCENESPHERE_H
+#define DCOLLIDE_DEFORMABLESCENESPHERE_H
+
+#include "scenes/scenebase.h"
+
+#include <d-collide/world.h>
+#include <d-collide/worldparameters.h>
+
+#include <string>
+#include <list>
+#include <vector>
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+namespace dcollide {
+    class World;
+    class Proxy;
+    class Mesh;
+    class WorldCollisions;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+class MyDeformableObjectNode;
+
+class DeformableSceneSpheres : public SceneBase {
+    public:
+        DeformableSceneSpheres(Ogre::Root* root);
+        virtual ~DeformableSceneSpheres();
+
+        virtual std::string getSceneDescription() const;
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+        virtual void addSceneSpecificWorldParameters(dcollide::WorldParameters& parameters) const;
+
+    private:
+        dcollide::real mAmplitude;
+        dcollide::real mPeriod;
+        dcollide::real mCircleAngle;
+        MyObjectNode* mStaticCloth;
+        MyDeformableObjectNode* mDeformingCloth;
+        std::vector<dcollide::Vector3> mClothDeformVector;
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physicsscenebase.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physicsscenebase.h (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physicsscenebase.h (revision 2943)
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_PHYSICSSCENEBASE_H
+#define DCOLLIDE_PHYSICSSCENEBASE_H
+
+#include "scenes/scenebase.h"
+
+#include <ode/ode.h>
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+
+/*!
+ * \brief base class for physics scenes
+ * 
+ * provides some additional functions and members needed
+ * for the simulation with ODE
+ */
+class PhysicsSceneBase : public SceneBase {
+public:
+    PhysicsSceneBase(Ogre::Root* root);
+    virtual ~PhysicsSceneBase();
+
+    bool initScene();
+    virtual inline bool getUsePhysics() const;
+    
+    inline dWorldID getOdeWorld() const;
+    void doPhysicsStep();
+
+    virtual void calculateCollisions(unsigned int flags);
+
+protected:
+    virtual void addInitialWorldParameters(dcollide::WorldParameters& parameters) const;
+
+private:
+    struct JointTemplate {
+        dcollide::CollisionInfo& collInfo;
+        dGeomID penetratingGeom;
+        dGeomID penetratedGeom;
+        dBodyID penetratingBody;
+        dBodyID penetratedBody;
+        
+        JointTemplate(dcollide::CollisionInfo& infoObj) : collInfo(infoObj) {
+            penetratingGeom = 0;
+            penetratedGeom = 0;
+            penetratingBody = 0;
+            penetratedBody = 0;
+        };
+    };
+    
+    void dampMotions();
+
+    void convertDCollideResultsToOde();
+    void createOdeContactJoint(JointTemplate& jointTemplate);
+    void addDampingAndFrictionParameters(dContact* contact);
+
+protected:
+    dJointGroupID mContactJoints;
+    dWorldID mOdeWorld;
+
+    /*!
+     * \brief stepsize used for stepping the physics world. DO NOT MODIFY
+     * 
+     * 
+     * The stepsize should be set once in the Scene constructor. As ODE
+     * recommends to use fixed stepsizes, you should not modify that value
+     * afterwards.
+     */
+    float mPhysicsSimStepsize;
+    
+    /*!
+     * \brief damping factor for linear-velocity-based friction simulation
+     * 
+     * should be between -1 (instant damping) and 0 (no damping)
+     * Used for ODE only
+     */
+    dReal mLinearDampingFactor;
+    
+    /*!
+     * \brief damping factor for angular-velocity-based friction simulation
+     * 
+     * Should be greater between 0 (no damping) and 1(stop every rotation instantly)
+     * Used for ODE only
+     */
+    dReal mAngularDampingFactor;
+
+    /*!
+     * \brief list of nodes with physics bodies whose movements will be damped
+     * 
+     * Used for ODE only
+     */
+    std::list<MyObjectNode*> mDampedBodyNodes;
+
+    /*!
+     * \brief Indicates whenether all contact joints should be removed from
+     *        the ODE world when beginning a new physics-step
+     * 
+     * This flag is useful for scenes which want to test the reaction of the
+     * physics simulation to pre defined collision responses.
+     * 
+     * Defaults to true.
+     */
+    bool mRemoveContactJoins;
+    
+    /*!
+     * \brief Indicates whenether the detected collision should be filled
+     *        into ODD as contact joins or not
+     * 
+     * This flag is useful for scenes which want to test the reaction of the
+     * physics simulation to pre defined collision responses.
+     * 
+     * Defaults to true.
+     */
+    bool mAddContactJoins;
+};
+
+inline dWorldID PhysicsSceneBase::getOdeWorld() const {
+    return mOdeWorld;
+}
+
+inline bool PhysicsSceneBase::getUsePhysics() const{
+    return true;
+}
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.cpp (revision 2943)
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "snookerscene.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "debug.h"
+
+#include "Ogre.h"
+
+#include <world.h>
+#include <shapes/shapes.h>
+#include <worldcollisions.h>
+#include <collisioninfo.h>
+#include <proxyfactory.h>
+
+#include <algorithm>
+
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+SnookerScene::SnookerScene(Ogre::Root* root)
+    : PhysicsSceneBase(root) {
+    mTable=0;
+    mBall1=0;
+    mBall2=0;
+    
+    
+    mPhysicsSimStepsize = 0.03;
+    mLinearDampingFactor = 0.001;
+    mAngularDampingFactor = 0.005;
+}
+
+SnookerScene::~SnookerScene() {
+
+}
+
+
+dcollide::Vector3 SnookerScene::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ */
+bool SnookerScene::initializeScene() {
+    dWorldSetGravity(mOdeWorld, 0,0,-10);
+    mCollisionWorld->setNarrowPhaseStrategySphereSphere(dcollide::NP_STRATEGY_SLOWEST_EXTENSIVE);
+            
+    //Table: Box, top at z=0, height = 20
+    //cusions: boxes
+    //balls: spheres
+    
+    // Top view:
+    // y=200
+    //  3-------------------2
+    //  |                   |
+    //  |                   |
+    //  |                   |
+    //  |                   |
+    //  0-------------------1
+    //origin               x=350
+    
+    //The table-proxy will contain 5 children
+    //one for the baseplate, and 4 cushions
+    
+    //the table will not receive a physics body and is considered to be
+    //"static environment" which is not affected by gravity.
+   mTable = new MyObjectNode(getCollisionWorld(), 0, dcollide::PROXYTYPE_FIXED);
+    
+    MyObjectNode* baseplate = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(350,200, 20),
+                                                dcollide::PROXYTYPE_FIXED);
+    baseplate->translate(dcollide::Vector3(0, 0, -20));
+
+    
+    MyObjectNode* cushion01 = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(350, 10, 10),
+                                                dcollide::PROXYTYPE_FIXED, true, false);
+    cushion01->translate(dcollide::Vector3(0, -10, 0));
+    
+    MyObjectNode* cushion23 = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(350, 10, 10),
+                                                dcollide::PROXYTYPE_FIXED, true, false);
+    cushion23->translate(dcollide::Vector3(0, 200, 0));
+    
+    MyObjectNode* cushion12 = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(10, 200, 10),
+                                                dcollide::PROXYTYPE_FIXED, true, false);
+    cushion12->translate(dcollide::Vector3(350, 0, 0));
+    
+    MyObjectNode* cushion30 = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(10, 200, 10),
+                                                dcollide::PROXYTYPE_FIXED, true, false);
+    cushion30->translate(dcollide::Vector3(-10, 0, 0));
+    
+    
+    mTable->addChild(baseplate);
+    mTable->addChild(cushion01);
+    mTable->addChild(cushion12);
+    mTable->addChild(cushion23);
+    mTable->addChild(cushion30);
+    
+
+    addTopLevelObject(mTable);
+
+
+    //spheres
+    mBall1 = new MyObjectNode(getCollisionWorld(),
+                           new dcollide::Sphere(5), dcollide::PROXYTYPE_RIGID);
+    mBall1->createPhysicsBody(mOdeWorld,  4);
+    mBall1->translate(100.0, 50.0, 40.0);
+    addTopLevelObject(mBall1);
+    
+    mBall2 = new MyObjectNode(getCollisionWorld(),
+                              new dcollide::Sphere(10), dcollide::PROXYTYPE_RIGID);
+    mBall2->createPhysicsBody(mOdeWorld,  20);
+    mBall2->translate(200.0, 100.0, 60.0);
+    
+    addTopLevelObject(mBall2);
+
+    //another ball, falling on top of ball 2
+    ball3 = new MyObjectNode(getCollisionWorld(),
+                              new dcollide::Sphere(10), dcollide::PROXYTYPE_RIGID);
+    ball3->createPhysicsBody(mOdeWorld,  20);
+    ball3->translate(205.0, 105.0, 200.0);
+    
+    addTopLevelObject(ball3);
+
+    //A box wich should hit a cushion
+    fallingBox = new MyObjectNode(getCollisionWorld(),
+                            new dcollide::Box(50, 20, 30), dcollide::PROXYTYPE_RIGID);
+
+
+    fallingBox->createPhysicsBody(mOdeWorld,  20);
+    fallingBox->translate(305, 100, 150);
+    //rotate 45 deg on x-axis.
+    fallingBox->rotate(45, 1, 0 , 0);
+    
+    addTopLevelObject(fallingBox);
+    
+    return true;
+}
+
+// Restart-function (r-key)
+void SnookerScene::restart() {
+    // reset the positions of the three balls
+    removeObject(mBall1);
+    removeObject(mBall2);
+    removeObject(ball3);
+
+    /*mBall1->setPosition(100.0, 50.0, 40.0);
+    mBall2->setPosition(200.0, 100.0, 60.0);
+    ball3->setPosition(205.0, 105.0, 200.0);*/
+    
+    //remove the falling box
+    removeObject(fallingBox);
+
+    //create the balls again
+    mBall1 = new MyObjectNode(getCollisionWorld(),
+                           new dcollide::Sphere(5), dcollide::PROXYTYPE_RIGID);
+    mBall1->createPhysicsBody(mOdeWorld,  4);
+    mBall1->translate(100.0, 50.0, 40.0);
+    addTopLevelObject(mBall1);
+    
+    mBall2 = new MyObjectNode(getCollisionWorld(),
+                              new dcollide::Sphere(10), dcollide::PROXYTYPE_RIGID);
+    mBall2->createPhysicsBody(mOdeWorld,  20);
+    mBall2->translate(200.0, 100.0, 60.0);
+    
+    addTopLevelObject(mBall2);
+
+    ball3 = new MyObjectNode(getCollisionWorld(),
+                              new dcollide::Sphere(10), dcollide::PROXYTYPE_RIGID);
+    ball3->createPhysicsBody(mOdeWorld,  20);
+    ball3->translate(205.0, 105.0, 200.0);
+    
+    addTopLevelObject(ball3);
+    
+    //create another falling box with the same specifications
+    fallingBox = new MyObjectNode(getCollisionWorld(),
+                            new dcollide::Box(50, 20, 30), dcollide::PROXYTYPE_RIGID);
+
+
+    fallingBox->createPhysicsBody(mOdeWorld,  20);
+    fallingBox->translate(305, 100, 150);
+    //rotate 45 deg on x-axis.
+    fallingBox->rotate(45, 1, 0 , 0);
+    
+    addTopLevelObject(fallingBox);
+
+    // delete all collision results
+    deleteCollisions();
+
+}
+
+void SnookerScene::startNextSceneFrame() {
+}
+
+std::string SnookerScene::getSceneDescription() const {
+    return "Some spheres on a table. Physics included";
+}
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/boxstackscene.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/boxstackscene.h (revision 2699)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/boxstackscene.h (revision 2699)
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_BOXSTACKSCENE_H
+#define DCOLLIDE_BOXSTACKSCENE_H
+
+#include "scenes/physicsscenebase.h"
+
+#include <string>
+#include <list>
+#include <map>
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+
+class BoxstackScene : public PhysicsSceneBase {
+    public:
+        BoxstackScene(Ogre::Root* root);
+        virtual ~BoxstackScene();
+
+        virtual std::string getSceneDescription() const;
+
+        //void applyCollisions(const dcollide::WorldCollisions& collisions);
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+
+    private:
+        void restart();
+        MyObjectNode* baseA;
+        MyObjectNode* baseB;
+        MyObjectNode* baseC;
+        MyObjectNode* baseD;
+        MyObjectNode* baseE;
+        MyObjectNode* baseF;
+        MyObjectNode* topA;
+        MyObjectNode* topB;
+        MyObjectNode* topC;
+        MyObjectNode* topD;
+        MyObjectNode* topE;
+        MyObjectNode* topF;
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.h
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.h (revision 2679)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/snookerscene.h (revision 2679)
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#ifndef DCOLLIDE_SNOOKERSCENE_H
+#define DCOLLIDE_SNOOKERSCENE_H
+
+#include "scenes/physicsscenebase.h"
+
+#include <string>
+#include <list>
+#include <map>
+
+namespace Ogre {
+    class Root;
+    class Light;
+    class Camera;
+    class SceneManager;
+    class SceneNode;
+    class ManualObject;
+}
+
+namespace dcollide {
+    class World;
+    class Proxy;
+    class Mesh;
+    class WorldCollisions;
+    class Vector3;
+    class Shape;
+}
+
+class OgreSceneObjectFactory;
+class MyObjectNode;
+
+class SnookerScene : public PhysicsSceneBase {
+    public:
+        SnookerScene(Ogre::Root* root);
+        virtual ~SnookerScene();
+
+        virtual std::string getSceneDescription() const;
+
+        //void applyCollisions(const dcollide::WorldCollisions& collisions);
+
+    protected:
+        virtual dcollide::Vector3 initialWorldDimension() const;
+        virtual bool initializeScene();
+        virtual void startNextSceneFrame();
+
+    private:
+        MyObjectNode* mTable;
+        MyObjectNode* mBall1;
+        MyObjectNode* mBall2;
+        MyObjectNode* ball3;
+        MyObjectNode* fallingBox;
+        void restart();
+};
+
+#endif
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/shakescene.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/shakescene.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/shakescene.cpp (revision 2943)
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "shakescene.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "debug.h"
+
+#include "Ogre.h"
+
+#include <world.h>
+#include <shapes/shapes.h>
+#include <worldcollisions.h>
+#include <collisioninfo.h>
+#include <proxyfactory.h>
+
+#include <algorithm>
+
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+ShakeScene::ShakeScene(Ogre::Root* root)  : PhysicsSceneBase(root) {
+    mPhysicsSimStepsize = 0.03;
+    mLinearDampingFactor = 0.005;
+    mAngularDampingFactor = 0.005;
+}
+
+ShakeScene::~ShakeScene() {
+
+}
+
+
+dcollide::Vector3 ShakeScene::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ */
+bool ShakeScene::initializeScene() {
+    dWorldSetGravity(mOdeWorld, 0,0,-10);
+
+    MyObjectNode* baseplate = new MyObjectNode( getCollisionWorld(),
+            new dcollide::Box(500,500, 20),
+                              dcollide::PROXYTYPE_FIXED);
+    baseplate->translate(dcollide::Vector3(-250, -250, -20));
+    addTopLevelObject(baseplate);
+
+    /*     z 
+     *     ^  -10    10 y
+     *  40 |   +-----+ /
+     *     |   |     |/
+     *     |   |     |
+     *  20 |   +-----+
+     *  20 | +---+ +---+
+     *     | |   | |   |
+     *   0 | +---+ +---+
+     *     +-----------------> x
+     *      -21 -1,0,1 21
+     */
+    
+    MyObjectNode* underBox1 =  new MyObjectNode(
+        getCollisionWorld(),new dcollide::Box(20,20,20), dcollide::PROXYTYPE_RIGID, true, false);
+    underBox1->setPosition(-29,0,0);
+    underBox1->createPhysicsBody(mOdeWorld,4);
+    addTopLevelObject(underBox1);
+    
+    MyObjectNode* underBox2 =  new MyObjectNode(
+            getCollisionWorld(),new dcollide::Box(20,20,20), dcollide::PROXYTYPE_RIGID, true, false);
+    underBox2->setPosition(9,0,0);
+    underBox2->createPhysicsBody(mOdeWorld,4);
+    addTopLevelObject(underBox2);
+    
+    MyObjectNode* TopBox =  new MyObjectNode(
+            getCollisionWorld(),new dcollide::Box(20,20,20), dcollide::PROXYTYPE_RIGID, true, false);
+    TopBox->setPosition(-10,0,20);
+    TopBox->createPhysicsBody(mOdeWorld,50);
+    addTopLevelObject(TopBox);
+
+    
+    // create my own wall
+    /*     z 
+     *     ^                +---+
+     *     |                |   |
+     *     |                +---+
+     *     |             +---+ +---+
+     *     |             |   | |   | 
+     *     |             +---+ +---+
+     *     |          +---+ +---+ +---+
+     *     |          |   | |   | |   |
+     *     |          +---+ +---+ +---+
+     +     |       +---+ +---+ +---+ +---+
+     *     |       |   | |   | |   | |   |
+     *     |       +---+ +---+ +---+ +---+
+     *     |    +---+ +---+ +---+ +---+ +---+
+     *     |    |   | |   | |   | |   | |   |
+     *     |    +---+ +---+ +---+ +---+ +---+
+     *     | +---+ +---+ +---+ +---+ +---+ +---+
+     *     | |   | |   | |   | |   | |   | |   |
+     *     | +---+ +---+ +---+ +---+ +---+ +---+
+     *     +---------------------------------------> x
+     *  -63,-43,-42,-22,-21,-1,0,1 21,22 42,43 63
+     *  2nd level: -31,-11,-10,10,11,31,32,52
+                              
+     */
+    int baseBoxes = 10;
+    int boxWidth = 20;
+    int boxDistance = 15;
+    for (int row = 0; row<baseBoxes;row++){
+        for (int i=0; i<baseBoxes-row; i++){
+            MyObjectNode* box = new MyObjectNode( getCollisionWorld(),
+                    new dcollide::Box(boxWidth,boxWidth,boxWidth),dcollide::PROXYTYPE_RIGID, true, false);
+            float nr = (baseBoxes-row)/2.0;
+            box->setPosition(-(nr*boxWidth+(nr-0.5)*boxDistance) + i*boxWidth+i*boxDistance, 100 , row*boxWidth );
+            box->createPhysicsBody(mOdeWorld,  2);
+            addTopLevelObject(box);
+        }
+    }
+    
+    // Gregors Wall
+    dcollide::real wallDistance = -100;
+    int baseboxes = 8;
+    for (int row = 0; row<baseboxes;row++){
+        for (int i=0; i<baseboxes-row; i++){
+            MyObjectNode* box = new MyObjectNode( getCollisionWorld(),
+                    new dcollide::Box(10,10, 10),
+                                      dcollide::PROXYTYPE_RIGID, true, false);
+            box->setPosition(-50 + (row * 15)/2 + i * 13, wallDistance , row*10);
+            box->createPhysicsBody(mOdeWorld,  4);
+            addTopLevelObject(box);
+        }
+    }
+
+
+    return true;
+}
+
+void ShakeScene::startNextSceneFrame() {
+}
+
+std::string ShakeScene::getSceneDescription() const {
+    return "One physikbody on top of two other. Why is it shaking?";
+}
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/collisionresponse.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/collisionresponse.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/collisionresponse.cpp (revision 2943)
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "collisionresponse.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "debug.h"
+
+#include "Ogre.h"
+
+#include <world.h>
+#include <shapes/shapes.h>
+#include <shapes/mesh/meshfactory.h>
+#include <worldcollisions.h>
+#include <collisioninfo.h>
+#include <proxyfactory.h>
+
+#include <algorithm>
+
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+CollisionResponse::CollisionResponse(Ogre::Root* root)
+            : PhysicsSceneBase(root) {
+        // Set mRandomSeed to 0 for no variation
+        // to a constant value for reproducable variation
+        // or to time(NULL) for true pseudo-randomness
+        mRandomSeed = 123;
+        mPhysicsSimStepsize = 0.01;
+    }
+
+    CollisionResponse::~CollisionResponse() {
+
+    }
+
+    dcollide::Vector3 CollisionResponse::initialWorldDimension() const {
+        return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+    }
+
+
+/*!
+     * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+     * object.
+     *
+     * \return TRUE on success, otherwise FALSE.
+ */
+    bool CollisionResponse::initializeScene() {
+        using namespace dcollide;
+
+        srand(mRandomSeed);
+
+        dWorldSetGravity(mOdeWorld, 0,0,-10);
+
+        Vector3 startPositionMoving(75, -75, -100);
+        Vector3 startPositionStatic(75, -75, -150);
+        Vector3 rowDistance(0, 50, 0);
+        Vector3 columnDistance(-50, 0, 0);
+
+        MeshFactory meshFactory;
+        
+        Vector3 temporaryStartPosition;
+        
+        // create the grid of static objects
+        for (int i = 0; i < 4; ++i) {
+            temporaryStartPosition = startPositionStatic + (rowDistance * i);
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Wedge(10, 20, 20),
+                        dcollide::PROXYTYPE_FIXED, true, false);           
+
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+
+            mStaticObjects.push_back(temporaryObjectNode);
+
+            temporaryStartPosition += columnDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        meshFactory.createTetraeder(Vector3(0, 0, 0),
+                            Vector3(15,0, 0),Vector3(10, 10, 0),
+                            Vector3(10, 10, 15)),
+                        dcollide::PROXYTYPE_FIXED, true, false);
+
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+            
+            mStaticObjects.push_back(temporaryObjectNode);          
+           
+            temporaryStartPosition += columnDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Box(Vector3(10.0, 10.0, 10.0)),
+                        dcollide::PROXYTYPE_FIXED, true, false);
+
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+
+            mStaticObjects.push_back(temporaryObjectNode);
+
+            temporaryStartPosition += columnDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Sphere(10),
+                        dcollide::PROXYTYPE_FIXED, true, false);
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+
+           mStaticObjects.push_back(temporaryObjectNode);  
+            
+        }
+
+        // create the grid of physically moving objects
+        for (int i = 0; i < 4; ++i) {
+            temporaryStartPosition = startPositionMoving + (columnDistance * i);
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Wedge(10, 20, 20),
+                        dcollide::PROXYTYPE_RIGID);         
+
+            temporaryObjectNode->createPhysicsBody(mOdeWorld,  5);
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+                Vector3 trans =
+                    Vector3(rand()%2 - 1, rand()%2 - 1, rand()%2 - 1);
+                temporaryObjectNode->translate(trans);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+           
+            mMovingObjects.push_back(temporaryObjectNode); 
+
+            temporaryStartPosition += rowDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        meshFactory.createTetraeder(Vector3(0, 0, 0),
+                            Vector3(15,0, 0),Vector3(10, 10, 0),
+                            Vector3(10, 10, 15)),
+                        dcollide::PROXYTYPE_RIGID);
+
+            temporaryObjectNode->createPhysicsBody(mOdeWorld,  5);
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+                Vector3 trans =
+                        Vector3(rand()%2 - 1, rand()%2 - 1, rand()%2 - 1);
+                temporaryObjectNode->translate(trans);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+            
+            mMovingObjects.push_back(temporaryObjectNode);            
+            
+            temporaryStartPosition += rowDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Box(Vector3(10.0, 10.0, 10.0)),
+                        dcollide::PROXYTYPE_RIGID);
+
+            temporaryObjectNode->createPhysicsBody(mOdeWorld,  5);
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+                Vector3 trans =
+                        Vector3(rand()%2 - 1, rand()%2 - 1, rand()%2 - 1);
+                temporaryObjectNode->translate(trans);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+            
+            mMovingObjects.push_back(temporaryObjectNode);            
+           
+            temporaryStartPosition += rowDistance;
+
+            temporaryObjectNode = new MyObjectNode(
+                        getCollisionWorld(),
+                        new Sphere(10),
+                        dcollide::PROXYTYPE_RIGID);
+
+            temporaryObjectNode->createPhysicsBody(mOdeWorld,  5);
+            temporaryObjectNode->translate(temporaryStartPosition);
+            if (mRandomSeed != 0) {
+                Matrix rot;
+                rot.rotate(rand(), 1, 0, 0);
+                rot.rotate(rand(), 0, 1, 0);
+                rot.rotate(rand(), 0, 0, 1);
+                temporaryObjectNode->rotate(rot);
+                Vector3 trans =
+                        Vector3(rand()%2 - 1, rand()%2 - 1, rand()%2 - 1);
+                temporaryObjectNode->translate(trans);
+            }
+            const_cast<ModelLoader::TextureInformation&> (temporaryObjectNode
+                    ->getTextureInformation()).setTransparent(0.5);
+            addTopLevelObject(temporaryObjectNode);
+           
+            mMovingObjects.push_back(temporaryObjectNode);  
+
+        }
+        
+        return true;
+    }
+    
+    // Restart-function (r-key)
+    void CollisionResponse::restart() {        
+
+        // delete all static objects
+        for(std::list<MyObjectNode*>::iterator j = mStaticObjects.begin(); j != mStaticObjects.end(); j++ ) {
+            removeObject(*j);            
+        }
+
+        // to clean up the list
+        mStaticObjects.clear(); 
+
+        // delete all moving objects        
+        for(std::list<MyObjectNode*>::iterator i = mMovingObjects.begin(); i != mMovingObjects.end(); i++ ) {
+            removeObject(*i);
+        }
+        
+        // to clean up the list
+        mMovingObjects.clear();
+        
+        // delete all collision results
+        deleteCollisions();
+        
+        // the actual restart
+        initializeScene();
+
+    }
+
+    void CollisionResponse::startNextSceneFrame() {
+        //TODO simulate friction: calculate velocities and apply damping forces
+
+        //General velocity-based damping force for all balls
+        //dReal damping = 0.1;
+
+        //const dReal* velocity = dBodyGetLinearVel(mBall2->getPhysicsBody());
+        //dBodyAddForce(mBall2->getPhysicsBody(), -damping * velocity[0], -damping * velocity[1], -damping * velocity[2]);
+    }
+
+    std::string CollisionResponse::getSceneDescription() const {
+        return "A 'matrix' of static, columnwise different shapes and its \n 'transpose' of physical renderred objects";
+    }
+/*
+    * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/wallscene.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/wallscene.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/wallscene.cpp (revision 2943)
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "wallscene.h"
+#include "dcollide-config_testapp.h"
+#include "myobjectnode.h"
+#include "debug.h"
+
+#include "Ogre.h"
+
+#include <world.h>
+#include <shapes/shapes.h>
+#include <worldcollisions.h>
+#include <collisioninfo.h>
+#include <proxyfactory.h>
+
+#include <algorithm>
+
+/*!
+ * Construct a new d-collide based scene object.
+ *
+ * The scene itself is not yet created, only the necessary data
+ * structures. Call \ref initializeScene to actually create a scene.
+ *
+ * \param root A pointer to the ogre root object. Ownership is NOT
+ * taken, the pointer will not be deleted by this class.
+ */
+WallScene::WallScene(Ogre::Root* root)
+    : PhysicsSceneBase(root) {
+    mPhysicsSimStepsize = 0.03;
+    mLinearDampingFactor = 0.005;
+    mAngularDampingFactor = 0.005;
+}
+
+WallScene::~WallScene() {
+
+}
+
+
+dcollide::Vector3 WallScene::initialWorldDimension() const {
+    return dcollide::Vector3(2048.0, 2048.0, 2048.0);
+}
+
+
+/*!
+ * Setup the actual scene, i.e. add objects to the \ref dcollide::World
+ * object.
+ *
+ * \return TRUE on success, otherwise FALSE.
+ */
+bool WallScene::initializeScene() {
+    dWorldSetGravity(mOdeWorld, 0,0,-10);
+    //dWorldSetContactSurfaceLayer(mOdeWorld, 2.0);
+    mCollisionWorld->setNarrowPhaseStrategySphereSphere(dcollide::NP_STRATEGY_SLOWEST_EXTENSIVE);
+            
+
+    
+    // Top view:
+    // z=200
+    //  ^
+    //  |                   
+    //  |               X   
+    //  |               X    
+    //  |               X    
+    //  0------------------->
+    //origin            x=300
+    
+    //The table-proxy will contain 5 children
+    //one for the baseplate, and 4 cushions
+    
+    //the table will not receive a physics body and is considered to be
+    //"static environment" which is not affected by gravity.
+
+    MyObjectNode* baseplate = new MyObjectNode( getCollisionWorld(),
+                                                new dcollide::Box(2000, 2000, 20),
+                                                dcollide::PROXYTYPE_FIXED);
+    baseplate->translate(dcollide::Vector3(-1000, -1000, -20));
+    addTopLevelObject(baseplate);
+
+    //create boxes for wall1 and wall2
+
+    for (int i = 0; i< 8+7+6+5+4+3+2+1; i++){
+        MyObjectNode* box = new MyObjectNode( getCollisionWorld(),
+                                                        new dcollide::Box(10,10, 10),
+                                                        dcollide::PROXYTYPE_RIGID, true, true);
+        box->createPhysicsBody(mOdeWorld,  1);
+        addTopLevelObject(box);
+        mWall1.push_back(box);
+        mDampedBodyNodes.push_back(box);
+            
+        MyObjectNode* box2 = new MyObjectNode( getCollisionWorld(),
+                                                        new dcollide::Box(10,10, 10),
+                                                        dcollide::PROXYTYPE_RIGID, true, true);
+        box2->createPhysicsBody(mOdeWorld,  5);
+        addTopLevelObject(box2);
+        mWall2.push_back(box2);
+        mDampedBodyNodes.push_back(box2);
+    }
+    restart();
+    return true;
+}
+
+/*!
+ * \brief wallscene special action: generate and fire a ball in camera direction
+ */
+void WallScene::action() {
+    double radius = 2 + (rand() % 5);
+    MyObjectNode* ball = new MyObjectNode(getCollisionWorld(),
+                           new dcollide::Sphere(radius), dcollide::PROXYTYPE_RIGID);
+    ball->createPhysicsBody(mOdeWorld,  1);
+    const Ogre::Vector3 camDirection = mOgreCamera->getDirection();
+    const Ogre::Vector3 camPos = mOgreCamera->getPosition();
+    
+    Ogre::Vector3 ballPosition = camPos + camDirection *2* radius
+                                        - mOgreCamera->getUp() * radius; 
+    ball->setPosition(ballPosition[0], ballPosition[1], ballPosition[2]);
+    
+    addTopLevelObject(ball);
+    mBalls.push_back(ball);
+    mDampedBodyNodes.push_back(ball);
+    
+    Ogre::Vector3 force =  camDirection * 3000;
+    dBodyAddForce(ball->getPhysicsBody(), force[0], force[1], force[2]);
+}
+
+void WallScene::restart() {
+    mDampedBodyNodes.clear();
+    //reset boxes
+    //Wall of Boxes
+    //x-value is constant
+    dcollide::real wallDistance = 100;
+    int baseboxes = 8;
+    int boxIndex = 0;
+    for (int row = 0; row<baseboxes;row++){
+        for (int i=0; i<baseboxes-row; i++){
+            MyObjectNode* box = mWall1[boxIndex];
+            box->setPosition(wallDistance, -50 + (row * 15)/2 + i * 13, row*10);
+            box->setRotation(dcollide::Matrix());
+            
+            dBodySetForce(box->getPhysicsBody(), 0,0,0);
+            dBodySetAngularVel(box->getPhysicsBody(), 0,0,0);
+            dBodySetLinearVel(box->getPhysicsBody(), 0,0,0);
+            
+            boxIndex++;
+            mDampedBodyNodes.push_back(box);
+        }
+    }
+    
+    wallDistance = 250;
+    boxIndex = 0;
+    for (int row = 0; row<baseboxes;row++){
+        for (int i=0; i<baseboxes-row; i++){
+            MyObjectNode* box = mWall2[boxIndex];
+            box->setPosition(wallDistance, -50 + (row * 15)/2 + i * 13, row*10);
+            box->setRotation(dcollide::Matrix());
+            
+            dBodySetForce(box->getPhysicsBody(), 0,0,0);
+            dBodySetAngularVel(box->getPhysicsBody(), 0,0,0);
+            dBodySetLinearVel(box->getPhysicsBody(), 0,0,0);
+            
+            boxIndex++;
+            mDampedBodyNodes.push_back(box);
+        }
+    }
+    
+    //delete all balls
+    for (std::list<MyObjectNode*>::iterator iter = mBalls.begin();
+    iter != mBalls.end(); ++iter){
+        MyObjectNode* ball = *iter;
+        removeObject(ball);
+    }
+    
+    mBalls.clear();
+
+    
+    deleteCollisions();
+}
+void WallScene::startNextSceneFrame() {
+}
+
+std::string WallScene::getSceneDescription() const {
+    return "a Wall of boxes is hit by some cannonballs.\nPush space to launch a cannonball in camera direction";
+}
+/*
+ * vim: et sw=4 ts=4
+ */
Index: /d-collide/tags/1.0.0/testapp/scenes/physics/rampscene.cpp
===================================================================
--- /d-collide/tags/1.0.0/testapp/scenes/physics/rampscene.cpp (revision 2943)
+++ /d-collide/tags/1.0.0/testapp/scenes/physics/rampscene.cpp (revision 2943)
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ *  Copyright (C) 2007 by the members of PG 510, University of Dortmund:       *
+ *              d-collide-devel@lists.sourceforge.net                          *
+ *
+ *     Andreas Beckermann, Christian Bode, Marcel Ens, Sebastian Ens,          *
+ *     Martin Fassbach, Maximilian Hegele, Daniel Haus, Oliver Horst,         *
+ *     Gregor Jochmann, Timo Loist, Marcel Nienhaus and Marc Schulz            *
+ *                                                                             *
+ *  All rights reserved.                                                       *
+ *                                                                             *
+ *  Redistribution and use in source and binary forms, with or without         *
+ *  modification, are permitted provided that the following conditions are met:*
+ *   - Redistributions of source code must retain the above copyright          *
+ *     notice, this list of conditions and the following disclaimer.           *
+ *   - Redistributions in binary form must reproduce the above copyright       *
+ *     notice, this list of conditions and the following disclaimer in the     *
+ *     documentation and/or other materials provided with the distribution.    *
+ *   - Neither the name of the PG510 nor the names of its contributors may be  *
+ *     used to endorse or promote products derived from this software without  *
+ *     specific prior written permission.                                      *
+ *                                                                             *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        *
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          *
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR      *
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
+ *  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   *
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,        *
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR         *
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING       *
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         *
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                *
+ *******************************************************************************/
+
+#include "rampscene.h"
+#include "dcollide-config_