diff --git a/CMakeLists.txt b/CMakeLists.txt
index acc474da3..26e662c97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF)
OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON)
OPTION(BUILD_SHARED_LIBS "Use shared libraries" OFF)
OPTION(USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD "Use btSoftMultiBodyDynamicsWorld" OFF)
+OPTION(BULLET2_USE_THREAD_LOCKS "Build Bullet 2 libraries with mutex locking around certain operations" OFF)
OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF)
OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF)
@@ -155,6 +156,13 @@ IF(USE_GRAPHICAL_BENCHMARK)
ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK)
ENDIF (USE_GRAPHICAL_BENCHMARK)
+IF(BULLET2_USE_THREAD_LOCKS)
+ ADD_DEFINITIONS( -DBT_THREADSAFE=1 )
+ IF (NOT MSVC)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ ENDIF (NOT MSVC)
+ENDIF (BULLET2_USE_THREAD_LOCKS)
+
IF (WIN32)
OPTION(USE_GLUT "Use Glut" ON)
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
@@ -195,8 +203,6 @@ ENDIF (OPENGL_FOUND)
#FIND_PACKAGE(GLU)
-
-
IF (APPLE)
FIND_LIBRARY(COCOA_LIBRARY Cocoa)
ENDIF()
@@ -211,7 +217,8 @@ IF(BUILD_PYBULLET)
FIND_PACKAGE(PythonLibs)
OPTION(BUILD_PYBULLET_NUMPY "Set when you want to build pybullet with NumPy support" OFF)
-
+ OPTION(BUILD_PYBULLET_ENET "Set when you want to build pybullet with enet UDP networking support" ON)
+
IF(BUILD_PYBULLET_NUMPY)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/build3/cmake)
#include(FindNumPy)
@@ -264,6 +271,15 @@ IF(BUILD_BULLET2_DEMOS)
IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/examples AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/examples)
SUBDIRS(examples)
ENDIF()
+
+ IF (BULLET2_USE_THREAD_LOCKS)
+ OPTION(BULLET2_MULTITHREADED_OPEN_MP_DEMO "Build Bullet 2 MultithreadedDemo using OpenMP (requires a compiler with OpenMP support)" OFF)
+ OPTION(BULLET2_MULTITHREADED_TBB_DEMO "Build Bullet 2 MultithreadedDemo using Intel Threading Building Blocks (requires the TBB library to be already installed)" OFF)
+ IF (MSVC)
+ OPTION(BULLET2_MULTITHREADED_PPL_DEMO "Build Bullet 2 MultithreadedDemo using Microsoft Parallel Patterns Library (requires MSVC compiler)" OFF)
+ ENDIF (MSVC)
+ ENDIF (BULLET2_USE_THREAD_LOCKS)
+
ENDIF(BUILD_BULLET2_DEMOS)
diff --git a/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h b/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h
index 49fb0dee0..2e2e8e322 100644
--- a/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h
+++ b/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h
@@ -553,6 +553,8 @@ typedef struct bInvalidHandle {
double m_deactivationTime;
double m_friction;
double m_rollingFriction;
+ double m_contactDamping;
+ double m_contactStiffness;
double m_restitution;
double m_hitFraction;
double m_ccdSweptSphereRadius;
@@ -585,6 +587,8 @@ typedef struct bInvalidHandle {
float m_deactivationTime;
float m_friction;
float m_rollingFriction;
+ float m_contactDamping;
+ float m_contactStiffness;
float m_restitution;
float m_hitFraction;
float m_ccdSweptSphereRadius;
diff --git a/README.md b/README.md
index 19d90086b..5c654bd04 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# Bullet Physics SDK
-This is the official C++ source code repository of the Bullet Physics SDK: real-time collision detection and multi-physics simulation for games, visual effects, robotics etc.
+This is the official C++ source code repository of the Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc.
New in Bullet 2.85: pybullet Python bindings, improved support for robotics and VR
diff --git a/build3/premake4.lua b/build3/premake4.lua
index f0de611fd..525996461 100644
--- a/build3/premake4.lua
+++ b/build3/premake4.lua
@@ -57,7 +57,7 @@
description = "Use Midi controller to control parameters"
}
--- --_OPTIONS["midi"] = "1";
+-- _OPTIONS["midi"] = "1";
newoption
{
@@ -73,8 +73,8 @@
newoption
{
- trigger = "enet",
- description = "Enable enet NAT punchthrough test"
+ trigger = "no-enet",
+ description = "Disable enet and enet tests"
}
newoption
@@ -237,6 +237,7 @@ end
language "C++"
+
if not _OPTIONS["no-demos"] then
include "../examples/ExampleBrowser"
include "../examples/OpenGLWindow"
@@ -261,14 +262,23 @@ end
if not _OPTIONS["no-test"] then
include "../test/SharedMemory"
- if _OPTIONS["enet"] then
- include "../examples/ThirdPartyLibs/enet"
- include "../test/enet/client"
- include "../test/enet/server"
- end
+
end
end
+ if _OPTIONS["midi"] then
+ include "../examples/ThirdPartyLibs/midi"
+ end
+
+ if not _OPTIONS["no-enet"] then
+ include "../examples/ThirdPartyLibs/enet"
+ include "../test/enet/nat_punchthrough/client"
+ include "../test/enet/nat_punchthrough/server"
+ include "../test/enet/chat/client"
+ include "../test/enet/chat/server"
+ defines {"BT_ENABLE_ENET"}
+ end
+
if _OPTIONS["no-bullet3"] then
print "--no-bullet3 implies --no-demos"
_OPTIONS["no-demos"] = "1"
diff --git a/build3/premake5.exe b/build3/premake5.exe
new file mode 100644
index 000000000..28bccbcb8
Binary files /dev/null and b/build3/premake5.exe differ
diff --git a/build_cmake_pybullet_win32.bat b/build_cmake_pybullet_win32.bat
new file mode 100644
index 000000000..f3e672899
--- /dev/null
+++ b/build_cmake_pybullet_win32.bat
@@ -0,0 +1,4 @@
+mkdir cm
+cd cm
+cmake -DBUILD_PYBULLET=ON -DCMAKE_BUILD_TYPE=Release -DPYTHON_INCLUDE_DIR=c:\python-3.5.2\include -DPYTHON_LIBRARY=c:\python-3.5.2\libs\python35.lib -DPYTHON_DEBUG_LIBRARY=c:\python-3.5.2\libs\python35_d.lib ..
+start .
diff --git a/build_visual_studio_vr_pybullet_double.bat b/build_visual_studio_vr_pybullet_double.bat
index 6ca0652b9..f4c43cbb5 100644
--- a/build_visual_studio_vr_pybullet_double.bat
+++ b/build_visual_studio_vr_pybullet_double.bat
@@ -16,6 +16,6 @@ del tmp1234.txt
cd build3
-premake4 --double --enable_openvr --enable_pybullet --python_include_dir="%myvar%/include" --python_lib_dir="%myvar%/libs" --targetdir="../bin" vs2010
+premake4 --double --midi --enable_openvr --enable_pybullet --python_include_dir="%myvar%/include" --python_lib_dir="%myvar%/libs" --targetdir="../bin" vs2010
start vs2010
diff --git a/data/gripper/wsg50_one_motor_gripper_free_base.sdf b/data/gripper/wsg50_one_motor_gripper_free_base.sdf
index 7fc3ed2b2..552c36d28 100644
--- a/data/gripper/wsg50_one_motor_gripper_free_base.sdf
+++ b/data/gripper/wsg50_one_motor_gripper_free_base.sdf
@@ -303,6 +303,10 @@
+
+
+
+
0.042 0 0.145 0 0 1.5708
0.2
@@ -343,6 +347,10 @@
+
+
+
+
-0.042 0 0.145 0 0 4.71239
0.2
diff --git a/data/gripper/wsg50_one_motor_gripper_left_finger.urdf b/data/gripper/wsg50_one_motor_gripper_left_finger.urdf
new file mode 100644
index 000000000..a5e58f6c4
--- /dev/null
+++ b/data/gripper/wsg50_one_motor_gripper_left_finger.urdf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/gripper/wsg50_one_motor_gripper_new_free_base.sdf b/data/gripper/wsg50_one_motor_gripper_new_free_base.sdf
index 68e2a0a6e..0358f7a6a 100644
--- a/data/gripper/wsg50_one_motor_gripper_new_free_base.sdf
+++ b/data/gripper/wsg50_one_motor_gripper_new_free_base.sdf
@@ -300,6 +300,10 @@
+
+ 1.0
+ 1.5
+
0.062 0 0.145 0 0 1.5708
0.2
@@ -340,6 +344,10 @@
+
+ 1.0
+ 1.5
+
-0.062 0 0.145 0 0 4.71239
0.2
diff --git a/data/gripper/wsg50_one_motor_gripper_no_finger.sdf b/data/gripper/wsg50_one_motor_gripper_no_finger.sdf
new file mode 100644
index 000000000..878b1ee14
--- /dev/null
+++ b/data/gripper/wsg50_one_motor_gripper_no_finger.sdf
@@ -0,0 +1,307 @@
+
+
+
+
+ 0 0 0.4 3.14 0 0
+
+
+
+
+
+ world
+ base_link
+
+ 0 0 1
+
+ -10
+ 10
+ 1
+ 1
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+ 0 0 0 0 0 0
+
+ 0 0 0 0 0 0
+ 1.2
+
+ 1
+ 0
+ 0
+ 1
+ 0
+ 1
+
+
+
+
+ 0 0 0 0 -0 0
+
+
+ 1 1 1
+ meshes/WSG50_110.stl
+
+
+
+
+
+
+
+
+
+
+ 0 0 0.03 0 0 0
+
+ 0 0 0 0 0 0
+ 0.1
+
+ 0.1
+ 0
+ 0
+ 0.1
+ 0
+ 0.1
+
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.02 0.02 0.02
+
+
+
+
+
+
+ motor
+ base_link
+
+ 0 0 1
+
+ -0.055
+ 0.001
+ 10.0
+ 10.0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+ 0 0 0.04 0 0 0
+
+ 0 0 0.035 0 0 0
+ 0.1
+
+ 0.1
+ 0
+ 0
+ 0.1
+ 0
+ 0.1
+
+
+
+ -0.03 0 0.01 0 -1.2 0
+
+
+ 0.02 0.02 0.07
+
+
+
+
+
+
+ left_hinge
+ motor
+
+ 0 1 0
+
+ -20.0
+ 20.0
+ 10
+ 10
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+
+ 0 0 0.04 0 0 0
+
+ 0 0 0.035 0 0 0
+ 0.1
+
+ 0.1
+ 0
+ 0
+ 0.1
+ 0
+ 0.1
+
+
+
+ 0.03 0 0.01 0 1.2 0
+
+
+ 0.02 0.02 0.07
+
+
+
+
+
+
+ right_hinge
+ motor
+
+ 0 1 0
+
+ -20.0
+ 20.0
+ 10
+ 10
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+
+ -0.055 0 0.06 0 -0 0
+
+ 0 0 0.0115 0 -0 0
+ 0.2
+
+ 0.1
+ 0
+ 0
+ 0.1
+ 0
+ 0.1
+
+
+
+
+ 0 0 -0.06 0 0 0
+
+
+ 0.001 0.001 0.001
+ meshes/GUIDE_WSG50_110.stl
+
+
+
+
+ 0 0 -0.037 0 0 0
+
+
+ 0.001 0.001 0.001
+ meshes/WSG-FMF.stl
+
+
+
+
+
+
+
+ gripper_left
+ base_link
+
+ 1 0 0
+
+ -0.01
+ 0.04
+ 1
+ 1
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+ 0.055 0 0.06 0 0 0
+
+ 0 0 0.0115 0 -0 0
+ 0.2
+
+ 0.1
+ 0
+ 0
+ 0.1
+ 0
+ 0.1
+
+
+
+
+ 0 0 -0.06 0 0 3.14159
+
+
+ 0.001 0.001 0.001
+ meshes/GUIDE_WSG50_110.stl
+
+
+
+
+ 0 0 -0.037 0 0 3.14159
+
+
+ 0.001 0.001 0.001
+ meshes/WSG-FMF.stl
+
+
+
+
+
+
+ gripper_right
+ base_link
+
+ 1 0 0
+
+ -0.04
+ 0.01
+ 1
+ 1
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/gripper/wsg50_one_motor_gripper_right_finger.urdf b/data/gripper/wsg50_one_motor_gripper_right_finger.urdf
new file mode 100644
index 000000000..c6257e399
--- /dev/null
+++ b/data/gripper/wsg50_one_motor_gripper_right_finger.urdf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/humanoid/LICENSE.txt b/data/humanoid/LICENSE.txt
new file mode 100644
index 000000000..8922f23f1
--- /dev/null
+++ b/data/humanoid/LICENSE.txt
@@ -0,0 +1,26 @@
+Copyright (c) 2009-2013, A. Hornung, University of Freiburg
+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 University of Freiburg 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.
\ No newline at end of file
diff --git a/data/humanoid/nao.urdf b/data/humanoid/nao.urdf
new file mode 100644
index 000000000..ed0f7cbbd
--- /dev/null
+++ b/data/humanoid/nao.urdf
@@ -0,0 +1,2663 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /nao_dcm
+ gazebo_ros_control/DefaultRobotHWSim
+
+
+
+
+
+ LHipYawPitch
+ RHipYawPitch
+ 1.0
+ 0.0
+
+
+ LHand
+ LFinger11
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LFinger12
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LFinger13
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LFinger21
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LFinger22
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LFinger23
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger11
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger12
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger13
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger21
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger22
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RFinger23
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LThumb1
+ -0.785398163398
+ 0.785398163398
+
+
+ LHand
+ LThumb2
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RThumb1
+ -0.785398163398
+ 0.785398163398
+
+
+ RHand
+ RThumb2
+ -0.785398163398
+ 0.785398163398
+
+
+ LFinger11_link
+
+
+ LFinger12_link
+
+
+ LFinger13_link
+
+
+ LFinger21_link
+
+
+ LFinger22_link
+
+
+ LFinger23_link
+
+
+ LThumb1_link
+
+
+ LThumb2_link
+
+
+ l_gripper
+
+
+ RFinger11_link
+
+
+ RFinger12_link
+
+
+ RFinger13_link
+
+
+ RFinger21_link
+
+
+ RFinger22_link
+
+
+ RFinger23_link
+
+
+ RThumb1_link
+
+
+ RThumb2_link
+
+
+ r_gripper
+
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+ 0.5
+ 0.5
+ false
+ true
+
+
+
+
+ 5.0
+
+ 1.06290551
+
+ 640
+ 480
+ R8G8B8
+
+
+ 0.3
+ 500
+
+
+ gaussian
+ 0.0
+ 0.007
+
+
+
+ nao_robot
+ true
+ 5.0
+ camera/top
+ image_raw
+ camera_info
+ CameraTop_optical_frame
+ 0.07
+ -0.0545211
+ 0.06919734
+ -0.0241095
+ -0.0112245
+ 0.0
+
+
+
+
+
+ 5.0
+
+ 1.06290551
+
+ 640
+ 480
+ R8G8B8
+
+
+ 0.05
+ 500
+
+
+ gaussian
+ 0.0
+ 0.007
+
+
+
+ /nao_robot
+ true
+ 5.0
+ camera_bottom
+ image_raw
+ camera_info
+ CameraBottom_optical_frame
+ 0.07
+ -0.0648764
+ 0.06125202
+ 0.00382815
+ -0.00551104
+ 0.0
+
+
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ RFsrFL_frame_collision
+
+
+ nao_robot
+ true
+ FSR/RFoot/FrontLeft
+ RFsrFL_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ RFsrFR_frame_collision
+
+
+ nao_robot
+ true
+ FSR/RFoot/FrontRight
+ RFsrFR_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ RFsrRL_frame_collision
+
+
+ nao_robot
+ true
+ FSR/RFoot/RearLeft
+ RFsrRL_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ RFsrRR_frame_collision
+
+
+ nao_robot
+ true
+ FSR/RFoot/RearRight
+ RFsrRR_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ LFsrFL_frame_collision
+
+
+ nao_robot
+ true
+ FSR/LFoot/FrontLeft
+ RFsrFL_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ LFsrFR_frame_collision
+
+
+ nao_robot
+ true
+ FSR/LFoot/FrontRight
+ LFsrFR_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ LFsrRL_frame_collision
+
+
+ nao_robot
+ true
+ FSR/LFoot/RearLeft
+ LFsrRL_frame
+
+
+
+
+ 0.5
+ 0.5
+ false
+ false
+ 1 0 0
+ 0.1
+ 0.003
+
+ 1
+ 20
+ false
+
+ LFsrRR_frame_collision
+
+
+ nao_robot
+ true
+ FSR/LFoot/RearRight
+ LFsrRR_frame
+
+
+
+
+
+
+ 0 0 0 0 0 0
+ 20
+ false
+
+
+
+ 5
+ 1
+ -0.2617993877991494
+ 0.2617993877991494
+
+
+
+ 5
+ 1
+ -0.13
+ 0.13
+
+
+
+
+ 0.025
+ 2.55
+ 1
+
+
+
+ nao_robot
+ 0.05
+ true
+ 20
+ sonar_left
+ LSonar_frame
+ 0.025
+ 2.55
+ 0.5235987755982988
+
+ ultrasound
+
+
+
+
+
+ 0 0 0 0 0 0
+ 20
+ false
+
+
+
+ 5
+ 1
+ -0.2617993877991494
+ 0.2617993877991494
+
+
+ 5
+ 1
+ -0.13
+ 0.13
+
+
+
+ 0.025
+ 2.55
+ 1
+
+
+
+ nao_robot
+ 0.05
+ true
+ 20
+ sonar_right
+ RSonar_frame
+ 0.025
+ 2.55
+ 0.5235987755982988
+ ultrasound
+
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 150.27
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 173.22
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 150.27
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 173.22
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 150.27
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 173.22
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 50.61
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 36.24
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 150.27
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 173.22
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 150.27
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 173.22
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 50.61
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+ PositionJointInterface
+ 36.24
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 130.85
+
+
+
+ transmission_interface/SimpleTransmission
+
+ PositionJointInterface
+
+
+
+ PositionJointInterface
+ 201.3
+
+
+
diff --git a/data/humanoid/nao_meshes/meshes/V40/HeadPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/HeadPitch_0.10.stl
new file mode 100644
index 000000000..f7d4abf23
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/HeadPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/HeadYaw_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/HeadYaw_0.10.stl
new file mode 100644
index 000000000..064ec3268
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/HeadYaw_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LAnklePitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LAnklePitch_0.10.stl
new file mode 100644
index 000000000..3e131386b
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LAnklePitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LAnkleRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LAnkleRoll_0.10.stl
new file mode 100644
index 000000000..361cd5cf0
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LAnkleRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LElbowRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LElbowRoll_0.10.stl
new file mode 100644
index 000000000..285486857
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LElbowRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger11_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger11_0.10.stl
new file mode 100644
index 000000000..088beaa2c
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger11_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger12_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger12_0.10.stl
new file mode 100644
index 000000000..c88375645
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger12_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger13_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger13_0.10.stl
new file mode 100644
index 000000000..49aeecafb
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger13_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger21_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger21_0.10.stl
new file mode 100644
index 000000000..7283509f5
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger21_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger22_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger22_0.10.stl
new file mode 100644
index 000000000..d096469cc
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger22_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LFinger23_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LFinger23_0.10.stl
new file mode 100644
index 000000000..fe488fead
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LFinger23_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LHipPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LHipPitch_0.10.stl
new file mode 100644
index 000000000..030e9e1f7
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LHipPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LHipRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LHipRoll_0.10.stl
new file mode 100644
index 000000000..ac6420665
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LHipRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LHipYawPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LHipYawPitch_0.10.stl
new file mode 100644
index 000000000..d6997c827
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LHipYawPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LKneePitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LKneePitch_0.10.stl
new file mode 100644
index 000000000..66b042675
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LKneePitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LShoulderPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LShoulderPitch_0.10.stl
new file mode 100644
index 000000000..8e761ec68
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LShoulderPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LShoulderRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LShoulderRoll_0.10.stl
new file mode 100644
index 000000000..6fd3957d4
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LShoulderRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LThumb1_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LThumb1_0.10.stl
new file mode 100644
index 000000000..d784d0dde
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LThumb1_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LThumb2_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LThumb2_0.10.stl
new file mode 100644
index 000000000..142741fb6
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LThumb2_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/LWristYaw_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/LWristYaw_0.10.stl
new file mode 100644
index 000000000..12fe18bf9
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/LWristYaw_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RAnklePitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RAnklePitch_0.10.stl
new file mode 100644
index 000000000..23afaf696
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RAnklePitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RAnkleRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RAnkleRoll_0.10.stl
new file mode 100644
index 000000000..c44b29ac9
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RAnkleRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RElbowRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RElbowRoll_0.10.stl
new file mode 100644
index 000000000..848b6afec
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RElbowRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger11_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger11_0.10.stl
new file mode 100644
index 000000000..95811bbf6
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger11_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger12_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger12_0.10.stl
new file mode 100644
index 000000000..be7cee53a
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger12_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger13_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger13_0.10.stl
new file mode 100644
index 000000000..a1f2ffbd3
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger13_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger21_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger21_0.10.stl
new file mode 100644
index 000000000..4a2af7468
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger21_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger22_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger22_0.10.stl
new file mode 100644
index 000000000..4260f54f2
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger22_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RFinger23_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RFinger23_0.10.stl
new file mode 100644
index 000000000..663cb1f5f
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RFinger23_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RHipPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RHipPitch_0.10.stl
new file mode 100644
index 000000000..9d6ef12e6
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RHipPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RHipRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RHipRoll_0.10.stl
new file mode 100644
index 000000000..36d67b9b4
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RHipRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RHipYawPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RHipYawPitch_0.10.stl
new file mode 100644
index 000000000..6697ebb7b
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RHipYawPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RKneePitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RKneePitch_0.10.stl
new file mode 100644
index 000000000..54fa06e50
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RKneePitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RShoulderPitch_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RShoulderPitch_0.10.stl
new file mode 100644
index 000000000..8333a4817
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RShoulderPitch_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RShoulderRoll_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RShoulderRoll_0.10.stl
new file mode 100644
index 000000000..3166375fe
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RShoulderRoll_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RThumb1_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RThumb1_0.10.stl
new file mode 100644
index 000000000..c7a3189cf
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RThumb1_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RThumb2_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RThumb2_0.10.stl
new file mode 100644
index 000000000..85777b605
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RThumb2_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/RWristYaw_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/RWristYaw_0.10.stl
new file mode 100644
index 000000000..abc0c67b3
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/RWristYaw_0.10.stl differ
diff --git a/data/humanoid/nao_meshes/meshes/V40/Torso_0.10.stl b/data/humanoid/nao_meshes/meshes/V40/Torso_0.10.stl
new file mode 100644
index 000000000..d4873f528
Binary files /dev/null and b/data/humanoid/nao_meshes/meshes/V40/Torso_0.10.stl differ
diff --git a/data/husky/meshes/base_link.stl b/data/husky/meshes/base_link.stl
new file mode 100644
index 000000000..db63bd20f
Binary files /dev/null and b/data/husky/meshes/base_link.stl differ
diff --git a/data/kiva_shelf/0_Bullet3Demo.txt b/data/kiva_shelf/0_Bullet3Demo.txt
deleted file mode 100644
index eb396d29f..000000000
--- a/data/kiva_shelf/0_Bullet3Demo.txt
+++ /dev/null
@@ -1,7 +0,0 @@
---start_demo_name=R2D2 Grasp
---mouse_move_multiplier=0.400000
---mouse_wheel_multiplier=0.010000
---background_color_red= 0.900000
---background_color_green= 0.900000
---background_color_blue= 1.000000
---fixed_timestep= 0.000000
diff --git a/data/kuka_iiwa/model_free_base.urdf b/data/kuka_iiwa/model_free_base.urdf
new file mode 100644
index 000000000..b87373346
--- /dev/null
+++ b/data/kuka_iiwa/model_free_base.urdf
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/multibody.bullet b/data/multibody.bullet
index 084ee5a8a..90aa45157 100644
Binary files a/data/multibody.bullet and b/data/multibody.bullet differ
diff --git a/data/plane.obj b/data/plane.obj
index 0b77a9912..606209531 100644
--- a/data/plane.obj
+++ b/data/plane.obj
@@ -2,14 +2,14 @@
# www.blender.org
mtllib plane.mtl
o Plane
-v 5.000000 -5.000000 0.000000
-v 5.000000 5.000000 0.000000
-v -5.000000 5.000000 0.000000
-v -5.000000 -5.000000 0.000000
+v 15.000000 -15.000000 0.000000
+v 15.000000 15.000000 0.000000
+v -15.000000 15.000000 0.000000
+v -15.000000 -15.000000 0.000000
-vt 5.000000 0.000000
-vt 5.000000 5.000000
-vt 0.000000 5.000000
+vt 15.000000 0.000000
+vt 15.000000 15.000000
+vt 0.000000 15.000000
vt 0.000000 0.000000
usemtl Material
diff --git a/data/plane.urdf b/data/plane.urdf
index b2c2d7659..480b0752f 100644
--- a/data/plane.urdf
+++ b/data/plane.urdf
@@ -1,6 +1,9 @@
+
+
+
@@ -16,9 +19,9 @@
-
+
-
+
diff --git a/data/quadruped/quadruped.urdf b/data/quadruped/quadruped.urdf
new file mode 100644
index 000000000..32e9c131c
--- /dev/null
+++ b/data/quadruped/quadruped.urdf
@@ -0,0 +1,712 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/torus/plane_only.mtl b/data/torus/plane_only.mtl
new file mode 100644
index 000000000..70d3ba1da
--- /dev/null
+++ b/data/torus/plane_only.mtl
@@ -0,0 +1,10 @@
+# Blender MTL File: 'None'
+# Material Count: 1
+
+newmtl None
+Ns 0
+Ka 0.000000 0.000000 0.000000
+Kd 0.8 0.8 0.8
+Ks 0.8 0.8 0.8
+d 1
+illum 2
diff --git a/data/torus/plane_only.obj b/data/torus/plane_only.obj
new file mode 100644
index 000000000..893742a69
--- /dev/null
+++ b/data/torus/plane_only.obj
@@ -0,0 +1,7913 @@
+# Blender v2.77 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib plane_only.mtl
+o Plane
+v -2.312398 -6.126618 0.566384
+v 6.032325 -2.575601 0.280679
+v -5.874205 2.203907 0.074895
+v 2.470518 5.754926 -0.210810
+v -5.804365 2.040563 0.084532
+v -5.734526 1.877220 0.094169
+v -5.664686 1.713876 0.103806
+v -5.594847 1.550532 0.113443
+v -5.525007 1.387189 0.123080
+v -5.455168 1.223845 0.132717
+v -5.385328 1.060502 0.142354
+v -5.315490 0.897157 0.151991
+v -5.245650 0.733814 0.161628
+v -5.175811 0.570470 0.171265
+v -5.105971 0.407127 0.180902
+v -5.036132 0.243783 0.190539
+v -4.966292 0.080439 0.200176
+v -4.896453 -0.082904 0.209813
+v -4.826613 -0.246248 0.219450
+v -4.756775 -0.409592 0.229087
+v -4.686935 -0.572935 0.238724
+v -4.617096 -0.736279 0.248362
+v -4.547256 -0.899623 0.257998
+v -4.477417 -1.062966 0.267636
+v -4.407578 -1.226310 0.277273
+v -4.337738 -1.389654 0.286910
+v -4.267900 -1.552997 0.296547
+v -4.198060 -1.716341 0.306184
+v -4.128221 -1.879685 0.315821
+v -4.058381 -2.043028 0.325458
+v -3.988542 -2.206372 0.335095
+v -3.918703 -2.369716 0.344732
+v -3.848863 -2.533059 0.354369
+v -3.779024 -2.696403 0.364006
+v -3.709185 -2.859747 0.373643
+v -3.639345 -3.023091 0.383280
+v -3.569506 -3.186434 0.392917
+v -3.499667 -3.349777 0.402554
+v -3.429827 -3.513121 0.412191
+v -3.359988 -3.676465 0.421829
+v -3.290149 -3.839808 0.431465
+v -3.220309 -4.003152 0.441103
+v -3.150470 -4.166496 0.450740
+v -3.080631 -4.329839 0.460377
+v -3.010791 -4.493183 0.470014
+v -2.940952 -4.656527 0.479651
+v -2.871112 -4.819870 0.489288
+v -2.801273 -4.983214 0.498925
+v -2.731434 -5.146557 0.508562
+v -2.661594 -5.309901 0.518199
+v -2.591755 -5.473244 0.527836
+v -2.521916 -5.636589 0.537473
+v -2.452076 -5.799932 0.547110
+v -2.382237 -5.963276 0.556747
+v -2.148776 -6.056991 0.560782
+v -1.985154 -5.987363 0.555180
+v -1.821532 -5.917735 0.549578
+v -1.657910 -5.848107 0.543976
+v -1.494288 -5.778480 0.538374
+v -1.330665 -5.708852 0.532772
+v -1.167043 -5.639224 0.527170
+v -1.003422 -5.569596 0.521568
+v -0.839799 -5.499969 0.515965
+v -0.676177 -5.430341 0.510363
+v -0.512555 -5.360713 0.504761
+v -0.348933 -5.291085 0.499159
+v -0.185311 -5.221457 0.493557
+v -0.021689 -5.151829 0.487955
+v 0.141933 -5.082201 0.482353
+v 0.305555 -5.012573 0.476751
+v 0.469177 -4.942945 0.471149
+v 0.632799 -4.873318 0.465547
+v 0.796421 -4.803690 0.459945
+v 0.960043 -4.734062 0.454343
+v 1.123665 -4.664434 0.448741
+v 1.287287 -4.594807 0.443139
+v 1.450909 -4.525179 0.437537
+v 1.614531 -4.455551 0.431935
+v 1.778153 -4.385922 0.426333
+v 1.941775 -4.316295 0.420731
+v 2.105397 -4.246667 0.415129
+v 2.269019 -4.177039 0.409527
+v 2.432641 -4.107412 0.403924
+v 2.596263 -4.037785 0.398322
+v 2.759885 -3.968157 0.392720
+v 2.923507 -3.898529 0.387118
+v 3.087129 -3.828902 0.381516
+v 3.250751 -3.759273 0.375914
+v 3.414372 -3.689645 0.370312
+v 3.577994 -3.620018 0.364710
+v 3.741616 -3.550390 0.359108
+v 3.905239 -3.480762 0.353506
+v 4.068861 -3.411134 0.347904
+v 4.232483 -3.341506 0.342302
+v 4.396105 -3.271878 0.336700
+v 4.559727 -3.202251 0.331098
+v 4.723349 -3.132623 0.325496
+v 4.886971 -3.062995 0.319894
+v 5.050592 -2.993367 0.314292
+v 5.214214 -2.923740 0.308690
+v 5.377837 -2.854112 0.303087
+v 5.541458 -2.784484 0.297485
+v 5.705081 -2.714856 0.291883
+v 5.868702 -2.645229 0.286281
+v 5.962485 -2.412257 0.271042
+v 5.892646 -2.248913 0.261405
+v 5.822806 -2.085569 0.251768
+v 5.752967 -1.922226 0.242131
+v 5.683127 -1.758882 0.232494
+v 5.613288 -1.595538 0.222857
+v 5.543449 -1.432195 0.213220
+v 5.473610 -1.268851 0.203583
+v 5.403770 -1.105507 0.193946
+v 5.333931 -0.942164 0.184309
+v 5.264091 -0.778820 0.174672
+v 5.194252 -0.615476 0.165035
+v 5.124413 -0.452132 0.155398
+v 5.054573 -0.288789 0.145761
+v 4.984735 -0.125445 0.136124
+v 4.914895 0.037898 0.126487
+v 4.845056 0.201242 0.116849
+v 4.775216 0.364586 0.107213
+v 4.705377 0.527929 0.097575
+v 4.635537 0.691273 0.087938
+v 4.565698 0.854617 0.078301
+v 4.495859 1.017960 0.068664
+v 4.426020 1.181304 0.059027
+v 4.356180 1.344648 0.049390
+v 4.286341 1.507991 0.039753
+v 4.216501 1.671335 0.030116
+v 4.146662 1.834678 0.020479
+v 4.076822 1.998022 0.010842
+v 4.006983 2.161365 0.001205
+v 3.937144 2.324709 -0.008432
+v 3.867305 2.488053 -0.018069
+v 3.797465 2.651397 -0.027706
+v 3.727626 2.814740 -0.037343
+v 3.657787 2.978083 -0.046980
+v 3.587947 3.141428 -0.056617
+v 3.518108 3.304771 -0.066254
+v 3.448268 3.468114 -0.075891
+v 3.378429 3.631458 -0.085528
+v 3.308590 3.794802 -0.095165
+v 3.238750 3.958145 -0.104803
+v 3.168911 4.121490 -0.114440
+v 3.099072 4.284833 -0.124077
+v 3.029233 4.448177 -0.133714
+v 2.959393 4.611520 -0.143351
+v 2.889554 4.774864 -0.152988
+v 2.819715 4.938208 -0.162625
+v 2.749875 5.101552 -0.172262
+v 2.680036 5.264896 -0.181899
+v 2.610196 5.428238 -0.191536
+v 2.540357 5.591582 -0.201173
+v 2.306895 5.685298 -0.205208
+v 2.143273 5.615670 -0.199606
+v 1.979651 5.546042 -0.194004
+v 1.816030 5.476415 -0.188402
+v 1.652407 5.406787 -0.182800
+v 1.488786 5.337159 -0.177198
+v 1.325163 5.267531 -0.171596
+v 1.161541 5.197904 -0.165994
+v 0.997919 5.128276 -0.160392
+v 0.834297 5.058648 -0.154789
+v 0.670675 4.989020 -0.149187
+v 0.507053 4.919393 -0.143585
+v 0.343431 4.849765 -0.137983
+v 0.179809 4.780137 -0.132381
+v 0.016187 4.710509 -0.126779
+v -0.147435 4.640882 -0.121177
+v -0.311057 4.571253 -0.115575
+v -0.474679 4.501625 -0.109973
+v -0.638301 4.431997 -0.104371
+v -0.801923 4.362370 -0.098769
+v -0.965545 4.292742 -0.093167
+v -1.129167 4.223114 -0.087565
+v -1.292789 4.153486 -0.081963
+v -1.456411 4.083858 -0.076361
+v -1.620033 4.014231 -0.070759
+v -1.783655 3.944603 -0.065157
+v -1.947277 3.874975 -0.059554
+v -2.110899 3.805346 -0.053952
+v -2.274521 3.735718 -0.048350
+v -2.438143 3.666091 -0.042748
+v -2.601765 3.596463 -0.037146
+v -2.765387 3.526835 -0.031544
+v -2.929009 3.457207 -0.025942
+v -3.092631 3.387580 -0.020340
+v -3.256253 3.317952 -0.014738
+v -3.419875 3.248324 -0.009136
+v -3.583497 3.178696 -0.003534
+v -3.747118 3.109069 0.002068
+v -3.910740 3.039441 0.007670
+v -4.074363 2.969813 0.013272
+v -4.237985 2.900185 0.018874
+v -4.401607 2.830558 0.024476
+v -4.565228 2.760930 0.030078
+v -4.728850 2.691302 0.035680
+v -4.892472 2.621674 0.041282
+v -5.056094 2.552047 0.046885
+v -5.219716 2.482419 0.052487
+v -5.383339 2.412791 0.058089
+v -5.546961 2.343162 0.063691
+v -5.710583 2.273535 0.069293
+v -5.640743 2.110191 0.078930
+v -5.407282 2.016475 0.082965
+v -5.173820 1.922760 0.087000
+v -4.940358 1.829044 0.091035
+v -4.706897 1.735328 0.095070
+v -4.473435 1.641612 0.099105
+v -4.239974 1.547897 0.103140
+v -4.006513 1.454180 0.107175
+v -3.773051 1.360465 0.111210
+v -3.539590 1.266749 0.115245
+v -3.306129 1.173033 0.119280
+v -3.072667 1.079317 0.123315
+v -2.839206 0.985601 0.127350
+v -2.605745 0.891885 0.131385
+v -2.372283 0.798169 0.135420
+v -2.138822 0.704454 0.139455
+v -1.905361 0.610738 0.143490
+v -1.671899 0.517022 0.147525
+v -1.438438 0.423306 0.151560
+v -1.204977 0.329590 0.155595
+v -0.971515 0.235874 0.159630
+v -0.738054 0.142159 0.163665
+v -0.504593 0.048443 0.167700
+v -0.271131 -0.045273 0.171735
+v -0.037670 -0.138989 0.175770
+v 0.195791 -0.232705 0.179805
+v 0.429253 -0.326421 0.183840
+v 0.662714 -0.420136 0.187875
+v 0.896175 -0.513852 0.191910
+v 1.129637 -0.607568 0.195945
+v 1.363098 -0.701284 0.199980
+v 1.596559 -0.795000 0.204015
+v 1.830021 -0.888716 0.208049
+v 2.063482 -0.982431 0.212084
+v 2.296943 -1.076147 0.216119
+v 2.530405 -1.169863 0.220154
+v 2.763866 -1.263579 0.224189
+v 2.997327 -1.357295 0.228224
+v 3.230788 -1.451011 0.232259
+v 3.464250 -1.544726 0.236294
+v 3.697711 -1.638442 0.240329
+v 3.931173 -1.732158 0.244364
+v 4.164635 -1.825874 0.248399
+v 4.398096 -1.919590 0.252434
+v 4.631557 -2.013306 0.256469
+v 4.865018 -2.107021 0.260504
+v 5.098479 -2.200737 0.264539
+v 5.331941 -2.294453 0.268574
+v 5.565402 -2.388169 0.272609
+v 5.798862 -2.481885 0.276644
+v -5.477121 2.179819 0.073328
+v -5.243659 2.086103 0.077363
+v -5.313498 2.249447 0.067726
+v -5.010198 1.992388 0.081398
+v -5.080037 2.155731 0.071761
+v -5.149877 2.319074 0.062124
+v -4.776736 1.898672 0.085433
+v -4.846576 2.062015 0.075796
+v -4.916415 2.225359 0.066159
+v -4.986255 2.388702 0.056522
+v -4.543275 1.804956 0.089468
+v -4.613114 1.968299 0.079831
+v -4.682954 2.131643 0.070194
+v -4.752793 2.294986 0.060557
+v -4.822633 2.458330 0.050920
+v -4.309813 1.711240 0.093503
+v -4.379653 1.874583 0.083866
+v -4.449492 2.037927 0.074229
+v -4.519332 2.201271 0.064592
+v -4.589171 2.364614 0.054955
+v -4.659011 2.527958 0.045318
+v -4.076352 1.617524 0.097538
+v -4.146192 1.780868 0.087901
+v -4.216031 1.944211 0.078264
+v -4.285871 2.107555 0.068627
+v -4.355710 2.270899 0.058990
+v -4.425550 2.434242 0.049352
+v -4.495389 2.597585 0.039715
+v -3.842891 1.523808 0.101573
+v -3.912730 1.687152 0.091936
+v -3.982570 1.850495 0.082299
+v -4.052409 2.013839 0.072662
+v -4.122249 2.177183 0.063025
+v -4.192088 2.340526 0.053387
+v -4.261928 2.503870 0.043751
+v -4.331767 2.667213 0.034113
+v -3.609429 1.430092 0.105608
+v -3.679269 1.593436 0.095971
+v -3.749108 1.756780 0.086334
+v -3.818948 1.920124 0.076697
+v -3.888787 2.083467 0.067060
+v -3.958627 2.246810 0.057422
+v -4.028465 2.410154 0.047786
+v -4.098306 2.573498 0.038148
+v -4.168145 2.736841 0.028511
+v -3.375968 1.336377 0.109643
+v -3.445807 1.499720 0.100006
+v -3.515647 1.663064 0.090369
+v -3.585486 1.826408 0.080732
+v -3.655326 1.989751 0.071095
+v -3.725165 2.153095 0.061457
+v -3.795005 2.316438 0.051821
+v -3.864844 2.479782 0.042183
+v -3.934684 2.643125 0.032546
+v -4.004523 2.806469 0.022909
+v -3.142507 1.242661 0.113678
+v -3.212346 1.406005 0.104041
+v -3.282185 1.569348 0.094404
+v -3.352025 1.732692 0.084767
+v -3.421864 1.896036 0.075130
+v -3.491704 2.059379 0.065492
+v -3.561543 2.222723 0.055856
+v -3.631382 2.386066 0.046218
+v -3.701222 2.549410 0.036581
+v -3.771061 2.712753 0.026944
+v -3.840901 2.876097 0.017307
+v -2.909045 1.148945 0.117713
+v -2.978885 1.312288 0.108076
+v -3.048724 1.475632 0.098439
+v -3.118563 1.638976 0.088801
+v -3.188403 1.802320 0.079165
+v -3.258242 1.965663 0.069527
+v -3.328082 2.129007 0.059891
+v -3.397921 2.292350 0.050253
+v -3.467761 2.455694 0.040616
+v -3.537600 2.619037 0.030979
+v -3.607439 2.782381 0.021342
+v -3.677279 2.945725 0.011705
+v -2.675584 1.055229 0.121748
+v -2.745423 1.218573 0.112111
+v -2.815263 1.381916 0.102473
+v -2.885102 1.545260 0.092836
+v -2.954941 1.708604 0.083200
+v -3.024781 1.871947 0.073562
+v -3.094620 2.035291 0.063925
+v -3.164460 2.198635 0.054288
+v -3.234299 2.361978 0.044651
+v -3.304139 2.525321 0.035014
+v -3.373978 2.688665 0.025377
+v -3.443818 2.852009 0.015740
+v -3.513657 3.015353 0.006103
+v -2.442123 0.961513 0.125782
+v -2.511962 1.124857 0.116146
+v -2.581802 1.288201 0.106508
+v -2.651641 1.451544 0.096871
+v -2.721480 1.614888 0.087234
+v -2.791320 1.778232 0.077597
+v -2.861159 1.941575 0.067960
+v -2.930999 2.104919 0.058323
+v -3.000838 2.268262 0.048686
+v -3.070677 2.431606 0.039049
+v -3.140517 2.594950 0.029412
+v -3.210356 2.758293 0.019775
+v -3.280196 2.921637 0.010138
+v -3.350035 3.084981 0.000501
+v -2.208661 0.867797 0.129817
+v -2.278501 1.031141 0.120181
+v -2.348340 1.194485 0.110543
+v -2.418180 1.357828 0.100906
+v -2.488019 1.521172 0.091269
+v -2.557858 1.684516 0.081632
+v -2.627698 1.847859 0.071995
+v -2.697537 2.011203 0.062358
+v -2.767377 2.174546 0.052721
+v -2.837216 2.337890 0.043084
+v -2.907056 2.501234 0.033447
+v -2.976895 2.664578 0.023810
+v -3.046734 2.827921 0.014173
+v -3.116574 2.991265 0.004536
+v -3.186413 3.154608 -0.005101
+v -1.975200 0.774081 0.133852
+v -2.045039 0.937425 0.124216
+v -2.114879 1.100769 0.114578
+v -2.184718 1.264112 0.104941
+v -2.254558 1.427456 0.095304
+v -2.324397 1.590800 0.085667
+v -2.394237 1.754144 0.076030
+v -2.464076 1.917487 0.066393
+v -2.533916 2.080831 0.056756
+v -2.603755 2.244174 0.047119
+v -2.673594 2.407518 0.037482
+v -2.743433 2.570862 0.027845
+v -2.813273 2.734205 0.018208
+v -2.883112 2.897548 0.008571
+v -2.952952 3.060892 -0.001066
+v -3.022791 3.224236 -0.010703
+v -1.741739 0.680366 0.137887
+v -1.811578 0.843709 0.128251
+v -1.881418 1.007053 0.118613
+v -1.951257 1.170397 0.108976
+v -2.021096 1.333740 0.099339
+v -2.090936 1.497084 0.089702
+v -2.160775 1.660428 0.080065
+v -2.230615 1.823772 0.070428
+v -2.300454 1.987115 0.060791
+v -2.370294 2.150458 0.051154
+v -2.440133 2.313802 0.041517
+v -2.509972 2.477146 0.031880
+v -2.579812 2.640490 0.022243
+v -2.649651 2.803833 0.012606
+v -2.719491 2.967177 0.002969
+v -2.789330 3.130521 -0.006668
+v -2.859169 3.293864 -0.016305
+v -1.508277 0.586650 0.141922
+v -1.578117 0.749993 0.132286
+v -1.647956 0.913337 0.122648
+v -1.717796 1.076681 0.113011
+v -1.787635 1.240025 0.103374
+v -1.857474 1.403368 0.093737
+v -1.927314 1.566712 0.084100
+v -1.997153 1.730055 0.074463
+v -2.066993 1.893399 0.064826
+v -2.136832 2.056743 0.055189
+v -2.206672 2.220086 0.045552
+v -2.276511 2.383430 0.035915
+v -2.346350 2.546774 0.026278
+v -2.416190 2.710117 0.016641
+v -2.486029 2.873461 0.007004
+v -2.555869 3.036804 -0.002633
+v -2.625708 3.200148 -0.012270
+v -2.695547 3.363492 -0.021907
+v -1.274816 0.492934 0.145957
+v -1.344656 0.656278 0.136321
+v -1.414495 0.819621 0.126683
+v -1.484334 0.982965 0.117046
+v -1.554174 1.146308 0.107409
+v -1.624013 1.309652 0.097772
+v -1.693853 1.472996 0.088135
+v -1.763692 1.636340 0.078498
+v -1.833531 1.799683 0.068861
+v -1.903371 1.963027 0.059224
+v -1.973210 2.126370 0.049587
+v -2.043050 2.289714 0.039950
+v -2.112889 2.453058 0.030313
+v -2.182729 2.616402 0.020676
+v -2.252568 2.779745 0.011039
+v -2.322407 2.943089 0.001402
+v -2.392247 3.106432 -0.008235
+v -2.462086 3.269776 -0.017872
+v -2.531925 3.433120 -0.027509
+v -1.041355 0.399218 0.149992
+v -1.111194 0.562562 0.140356
+v -1.181034 0.725905 0.130718
+v -1.250873 0.889249 0.121081
+v -1.320712 1.052593 0.111444
+v -1.390552 1.215936 0.101807
+v -1.460391 1.379280 0.092170
+v -1.530231 1.542624 0.082533
+v -1.600070 1.705968 0.072896
+v -1.669910 1.869311 0.063259
+v -1.739749 2.032655 0.053622
+v -1.809589 2.195998 0.043985
+v -1.879428 2.359342 0.034348
+v -1.949267 2.522686 0.024711
+v -2.019107 2.686029 0.015074
+v -2.088946 2.849373 0.005437
+v -2.158785 3.012717 -0.004200
+v -2.228625 3.176060 -0.013837
+v -2.298464 3.339404 -0.023474
+v -2.368304 3.502747 -0.033111
+v -0.807893 0.305502 0.154027
+v -0.877733 0.468846 0.144391
+v -0.947572 0.632190 0.134753
+v -1.017412 0.795533 0.125116
+v -1.087251 0.958877 0.115479
+v -1.157091 1.122221 0.105842
+v -1.226930 1.285564 0.096205
+v -1.296769 1.448908 0.086568
+v -1.366609 1.612251 0.076931
+v -1.436448 1.775595 0.067294
+v -1.506288 1.938939 0.057657
+v -1.576127 2.102283 0.048020
+v -1.645967 2.265626 0.038383
+v -1.715806 2.428969 0.028746
+v -1.785645 2.592313 0.019109
+v -1.855485 2.755657 0.009472
+v -1.925324 2.919001 -0.000165
+v -1.995163 3.082345 -0.009802
+v -2.065003 3.245688 -0.019439
+v -2.134842 3.409032 -0.029076
+v -2.204681 3.572375 -0.038713
+v -0.574432 0.211786 0.158062
+v -0.644271 0.375130 0.148426
+v -0.714111 0.538474 0.138788
+v -0.783950 0.701817 0.129151
+v -0.853790 0.865161 0.119514
+v -0.923629 1.028505 0.109877
+v -0.993469 1.191848 0.100240
+v -1.063308 1.355192 0.090603
+v -1.133147 1.518536 0.080966
+v -1.202987 1.681879 0.071329
+v -1.272826 1.845223 0.061692
+v -1.342666 2.008567 0.052055
+v -1.412505 2.171911 0.042418
+v -1.482344 2.335254 0.032781
+v -1.552184 2.498598 0.023144
+v -1.622023 2.661941 0.013507
+v -1.691863 2.825285 0.003870
+v -1.761702 2.988628 -0.005767
+v -1.831541 3.151972 -0.015404
+v -1.901381 3.315316 -0.025041
+v -1.971220 3.478660 -0.034678
+v -2.041059 3.642003 -0.044315
+v -0.340971 0.118071 0.162097
+v -0.410810 0.281414 0.152461
+v -0.480650 0.444758 0.142823
+v -0.550489 0.608102 0.133186
+v -0.620328 0.771445 0.123549
+v -0.690168 0.934789 0.113912
+v -0.760007 1.098133 0.104275
+v -0.829847 1.261476 0.094638
+v -0.899686 1.424820 0.085001
+v -0.969525 1.588164 0.075364
+v -1.039365 1.751507 0.065727
+v -1.109204 1.914851 0.056090
+v -1.179044 2.078194 0.046453
+v -1.248883 2.241538 0.036816
+v -1.318722 2.404882 0.027179
+v -1.388562 2.568226 0.017542
+v -1.458401 2.731569 0.007905
+v -1.528241 2.894913 -0.001732
+v -1.598080 3.058257 -0.011369
+v -1.667919 3.221600 -0.021006
+v -1.737759 3.384944 -0.030643
+v -1.807598 3.548288 -0.040280
+v -1.877437 3.711631 -0.049917
+v -0.107509 0.024355 0.166132
+v -0.177349 0.187698 0.156495
+v -0.247188 0.351042 0.146858
+v -0.317028 0.514386 0.137221
+v -0.386867 0.677729 0.127584
+v -0.456706 0.841073 0.117947
+v -0.526546 1.004417 0.108310
+v -0.596385 1.167760 0.098673
+v -0.666225 1.331104 0.089036
+v -0.736064 1.494448 0.079399
+v -0.805903 1.657791 0.069762
+v -0.875743 1.821135 0.060125
+v -0.945582 1.984479 0.050488
+v -1.015422 2.147822 0.040851
+v -1.085261 2.311166 0.031214
+v -1.155100 2.474510 0.021577
+v -1.224940 2.637853 0.011940
+v -1.294779 2.801197 0.002303
+v -1.364619 2.964541 -0.007334
+v -1.434458 3.127884 -0.016971
+v -1.504297 3.291228 -0.026608
+v -1.574137 3.454572 -0.036245
+v -1.643976 3.617915 -0.045882
+v -1.713815 3.781258 -0.055519
+v 0.125952 -0.069361 0.170167
+v 0.056113 0.093983 0.160530
+v -0.013727 0.257326 0.150893
+v -0.083566 0.420670 0.141256
+v -0.153406 0.584014 0.131619
+v -0.223245 0.747357 0.121982
+v -0.293084 0.910701 0.112345
+v -0.362924 1.074044 0.102708
+v -0.432763 1.237388 0.093071
+v -0.502603 1.400732 0.083434
+v -0.572442 1.564076 0.073797
+v -0.642281 1.727419 0.064160
+v -0.712121 1.890763 0.054523
+v -0.781960 2.054106 0.044886
+v -0.851800 2.217450 0.035249
+v -0.921639 2.380794 0.025612
+v -0.991478 2.544138 0.015975
+v -1.061318 2.707481 0.006338
+v -1.131157 2.870825 -0.003299
+v -1.200997 3.034168 -0.012936
+v -1.270836 3.197512 -0.022573
+v -1.340675 3.360856 -0.032210
+v -1.410515 3.524200 -0.041847
+v -1.480354 3.687543 -0.051485
+v -1.550194 3.850887 -0.061122
+v 0.359413 -0.163077 0.174202
+v 0.289574 0.000267 0.164565
+v 0.219735 0.163610 0.154928
+v 0.149895 0.326954 0.145291
+v 0.080056 0.490298 0.135654
+v 0.010216 0.653641 0.126017
+v -0.059623 0.816985 0.116380
+v -0.129462 0.980329 0.106743
+v -0.199302 1.143672 0.097106
+v -0.269141 1.307016 0.087469
+v -0.338981 1.470360 0.077832
+v -0.408820 1.633703 0.068195
+v -0.478659 1.797047 0.058558
+v -0.548499 1.960391 0.048921
+v -0.618338 2.123734 0.039284
+v -0.688178 2.287078 0.029647
+v -0.758017 2.450422 0.020010
+v -0.827856 2.613765 0.010373
+v -0.897696 2.777109 0.000736
+v -0.967535 2.940452 -0.008901
+v -1.037375 3.103796 -0.018538
+v -1.107214 3.267140 -0.028175
+v -1.177053 3.430484 -0.037812
+v -1.246893 3.593827 -0.047450
+v -1.316732 3.757171 -0.057087
+v -1.386572 3.920515 -0.066724
+v 0.592875 -0.256793 0.178237
+v 0.523035 -0.093449 0.168600
+v 0.453196 0.069894 0.158963
+v 0.383356 0.233238 0.149326
+v 0.313517 0.396582 0.139689
+v 0.243678 0.559926 0.130052
+v 0.173838 0.723269 0.120415
+v 0.103999 0.886613 0.110778
+v 0.034160 1.049956 0.101141
+v -0.035680 1.213300 0.091504
+v -0.105519 1.376644 0.081867
+v -0.175359 1.539987 0.072230
+v -0.245198 1.703331 0.062593
+v -0.315037 1.866675 0.052956
+v -0.384877 2.030019 0.043319
+v -0.454716 2.193362 0.033682
+v -0.524556 2.356706 0.024045
+v -0.594395 2.520050 0.014408
+v -0.664234 2.683393 0.004771
+v -0.734074 2.846737 -0.004866
+v -0.803913 3.010080 -0.014503
+v -0.873753 3.173424 -0.024140
+v -0.943592 3.336768 -0.033778
+v -1.013431 3.500112 -0.043415
+v -1.083271 3.663455 -0.053052
+v -1.153110 3.826799 -0.062689
+v -1.222950 3.990143 -0.072326
+v 0.826336 -0.350509 0.182272
+v 0.756497 -0.187165 0.172635
+v 0.686657 -0.023821 0.162998
+v 0.616818 0.139522 0.153361
+v 0.546978 0.302866 0.143724
+v 0.477139 0.466210 0.134087
+v 0.407299 0.629553 0.124450
+v 0.337460 0.792897 0.114813
+v 0.267621 0.956241 0.105176
+v 0.197781 1.119584 0.095539
+v 0.127942 1.282928 0.085902
+v 0.058103 1.446272 0.076265
+v -0.011737 1.609615 0.066628
+v -0.081576 1.772959 0.056991
+v -0.151416 1.936302 0.047354
+v -0.221255 2.099646 0.037717
+v -0.291094 2.262990 0.028080
+v -0.360934 2.426333 0.018443
+v -0.430773 2.589677 0.008806
+v -0.500613 2.753021 -0.000831
+v -0.570452 2.916364 -0.010468
+v -0.640291 3.079708 -0.020105
+v -0.710131 3.243052 -0.029743
+v -0.779970 3.406395 -0.039380
+v -0.849809 3.569739 -0.049017
+v -0.919649 3.733083 -0.058654
+v -0.989488 3.896427 -0.068291
+v -1.059328 4.059771 -0.077928
+v 1.059797 -0.444224 0.186307
+v 0.989958 -0.280881 0.176670
+v 0.920118 -0.117537 0.167033
+v 0.850279 0.045806 0.157396
+v 0.780440 0.209150 0.147759
+v 0.710600 0.372494 0.138122
+v 0.640761 0.535838 0.128485
+v 0.570921 0.699181 0.118848
+v 0.501082 0.862525 0.109211
+v 0.431243 1.025868 0.099574
+v 0.361403 1.189212 0.089937
+v 0.291564 1.352556 0.080300
+v 0.221724 1.515899 0.070663
+v 0.151885 1.679243 0.061026
+v 0.082046 1.842587 0.051389
+v 0.012206 2.005930 0.041752
+v -0.057633 2.169274 0.032115
+v -0.127473 2.332618 0.022478
+v -0.197312 2.495961 0.012841
+v -0.267151 2.659305 0.003203
+v -0.336991 2.822649 -0.006433
+v -0.406830 2.985992 -0.016070
+v -0.476670 3.149336 -0.025708
+v -0.546509 3.312680 -0.035345
+v -0.616348 3.476023 -0.044982
+v -0.686188 3.639367 -0.054619
+v -0.756027 3.802711 -0.064256
+v -0.825866 3.966055 -0.073893
+v -0.895706 4.129398 -0.083530
+v 1.293259 -0.537940 0.190342
+v 1.223419 -0.374597 0.180705
+v 1.153580 -0.211253 0.171068
+v 1.083740 -0.047909 0.161431
+v 1.013901 0.115434 0.151794
+v 0.944062 0.278778 0.142157
+v 0.874222 0.442122 0.132520
+v 0.804383 0.605465 0.122883
+v 0.734543 0.768809 0.113246
+v 0.664704 0.932153 0.103609
+v 0.594865 1.095496 0.093972
+v 0.525025 1.258840 0.084335
+v 0.455186 1.422184 0.074698
+v 0.385347 1.585527 0.065061
+v 0.315507 1.748871 0.055424
+v 0.245668 1.912214 0.045787
+v 0.175828 2.075558 0.036150
+v 0.105989 2.238902 0.026513
+v 0.036150 2.402245 0.016876
+v -0.033690 2.565589 0.007238
+v -0.103529 2.728933 -0.002398
+v -0.173369 2.892277 -0.012035
+v -0.243208 3.055620 -0.021673
+v -0.313048 3.218964 -0.031310
+v -0.382887 3.382308 -0.040947
+v -0.452726 3.545651 -0.050584
+v -0.522565 3.708995 -0.060221
+v -0.592405 3.872339 -0.069858
+v -0.662244 4.035683 -0.079495
+v -0.732084 4.199026 -0.089132
+v 1.526720 -0.631656 0.194377
+v 1.456881 -0.468312 0.184740
+v 1.387041 -0.304969 0.175103
+v 1.317202 -0.141625 0.165466
+v 1.247363 0.021719 0.155829
+v 1.177523 0.185062 0.146192
+v 1.107684 0.348406 0.136555
+v 1.037845 0.511750 0.126918
+v 0.968005 0.675093 0.117281
+v 0.898166 0.838437 0.107644
+v 0.828327 1.001781 0.098007
+v 0.758487 1.165124 0.088370
+v 0.688648 1.328468 0.078733
+v 0.618808 1.491812 0.069096
+v 0.548969 1.655155 0.059459
+v 0.479130 1.818499 0.049822
+v 0.409290 1.981842 0.040185
+v 0.339451 2.145186 0.030548
+v 0.269611 2.308530 0.020911
+v 0.199772 2.471873 0.011274
+v 0.129933 2.635217 0.001636
+v 0.060093 2.798561 -0.008000
+v -0.009746 2.961904 -0.017638
+v -0.079586 3.125248 -0.027275
+v -0.149425 3.288592 -0.036912
+v -0.219265 3.451936 -0.046549
+v -0.289104 3.615279 -0.056186
+v -0.358943 3.778623 -0.065823
+v -0.428783 3.941966 -0.075460
+v -0.498622 4.105311 -0.085097
+v -0.568462 4.268654 -0.094734
+v 1.760181 -0.725372 0.198412
+v 1.690342 -0.562028 0.188775
+v 1.620502 -0.398685 0.179138
+v 1.550663 -0.235341 0.169501
+v 1.480824 -0.071997 0.159864
+v 1.410985 0.091346 0.150227
+v 1.341145 0.254690 0.140590
+v 1.271306 0.418034 0.130953
+v 1.201466 0.581377 0.121316
+v 1.131627 0.744721 0.111679
+v 1.061788 0.908065 0.102042
+v 0.991948 1.071408 0.092405
+v 0.922109 1.234752 0.082768
+v 0.852270 1.398096 0.073131
+v 0.782430 1.561439 0.063494
+v 0.712591 1.724783 0.053857
+v 0.642752 1.888126 0.044220
+v 0.572912 2.051470 0.034583
+v 0.503073 2.214814 0.024946
+v 0.433233 2.378157 0.015309
+v 0.363394 2.541501 0.005672
+v 0.293555 2.704845 -0.003965
+v 0.223715 2.868189 -0.013603
+v 0.153876 3.031532 -0.023240
+v 0.084036 3.194876 -0.032877
+v 0.014197 3.358220 -0.042514
+v -0.055643 3.521563 -0.052151
+v -0.125482 3.684907 -0.061788
+v -0.195321 3.848251 -0.071425
+v -0.265161 4.011594 -0.081062
+v -0.335000 4.174939 -0.090699
+v -0.404840 4.338282 -0.100336
+v 1.993642 -0.819088 0.202447
+v 1.923803 -0.655744 0.192810
+v 1.853964 -0.492400 0.183173
+v 1.784124 -0.329057 0.173536
+v 1.714285 -0.165713 0.163899
+v 1.644446 -0.002369 0.154262
+v 1.574606 0.160974 0.144625
+v 1.504767 0.324318 0.134988
+v 1.434928 0.487662 0.125351
+v 1.365088 0.651005 0.115714
+v 1.295249 0.814349 0.106077
+v 1.225410 0.977692 0.096440
+v 1.155570 1.141036 0.086803
+v 1.085731 1.304380 0.077166
+v 1.015892 1.467724 0.067529
+v 0.946052 1.631067 0.057892
+v 0.876213 1.794411 0.048255
+v 0.806373 1.957754 0.038618
+v 0.736534 2.121098 0.028981
+v 0.666695 2.284442 0.019344
+v 0.596855 2.447785 0.009706
+v 0.527016 2.611129 0.000069
+v 0.457176 2.774473 -0.009568
+v 0.387337 2.937817 -0.019205
+v 0.317498 3.101161 -0.028842
+v 0.247658 3.264504 -0.038479
+v 0.177819 3.427847 -0.048116
+v 0.107979 3.591191 -0.057753
+v 0.038140 3.754535 -0.067390
+v -0.031699 3.917878 -0.077027
+v -0.101539 4.081222 -0.086664
+v -0.171378 4.244566 -0.096301
+v -0.241217 4.407909 -0.105938
+v 2.227104 -0.912804 0.206482
+v 2.157264 -0.749460 0.196845
+v 2.087425 -0.586116 0.187208
+v 2.017586 -0.422773 0.177571
+v 1.947746 -0.259429 0.167934
+v 1.877907 -0.096085 0.158297
+v 1.808068 0.067258 0.148660
+v 1.738228 0.230602 0.139023
+v 1.668389 0.393946 0.129386
+v 1.598550 0.557289 0.119749
+v 1.528710 0.720633 0.110112
+v 1.458871 0.883977 0.100475
+v 1.389032 1.047320 0.090838
+v 1.319192 1.210664 0.081201
+v 1.249353 1.374008 0.071564
+v 1.179514 1.537351 0.061927
+v 1.109674 1.700695 0.052290
+v 1.039835 1.864038 0.042653
+v 0.969995 2.027382 0.033016
+v 0.900156 2.190726 0.023379
+v 0.830317 2.354070 0.013741
+v 0.760477 2.517413 0.004105
+v 0.690638 2.680757 -0.005533
+v 0.620798 2.844100 -0.015170
+v 0.550959 3.007444 -0.024807
+v 0.481119 3.170788 -0.034444
+v 0.411280 3.334132 -0.044081
+v 0.341441 3.497475 -0.053718
+v 0.271601 3.660819 -0.063355
+v 0.201762 3.824162 -0.072992
+v 0.131922 3.987506 -0.082629
+v 0.062083 4.150850 -0.092266
+v -0.007756 4.314194 -0.101903
+v -0.077596 4.477537 -0.111540
+v 2.460565 -1.006519 0.210517
+v 2.390726 -0.843176 0.200880
+v 2.320886 -0.679832 0.191243
+v 2.251047 -0.516488 0.181606
+v 2.181208 -0.353145 0.171969
+v 2.111368 -0.189801 0.162332
+v 2.041529 -0.026457 0.152695
+v 1.971690 0.136886 0.143058
+v 1.901850 0.300230 0.133421
+v 1.832011 0.463574 0.123784
+v 1.762172 0.626917 0.114147
+v 1.692332 0.790261 0.104510
+v 1.622493 0.953604 0.094873
+v 1.552653 1.116948 0.085236
+v 1.482814 1.280292 0.075599
+v 1.412975 1.443635 0.065962
+v 1.343135 1.606979 0.056325
+v 1.273296 1.770323 0.046688
+v 1.203457 1.933666 0.037051
+v 1.133617 2.097010 0.027414
+v 1.063778 2.260354 0.017776
+v 0.993939 2.423697 0.008140
+v 0.924099 2.587041 -0.001498
+v 0.854260 2.750385 -0.011135
+v 0.784420 2.913728 -0.020772
+v 0.714581 3.077072 -0.030409
+v 0.644741 3.240416 -0.040046
+v 0.574902 3.403759 -0.049683
+v 0.505063 3.567103 -0.059320
+v 0.435223 3.730447 -0.068957
+v 0.365384 3.893790 -0.078594
+v 0.295545 4.057134 -0.088231
+v 0.225705 4.220478 -0.097868
+v 0.155866 4.383822 -0.107505
+v 0.086026 4.547165 -0.117142
+v 2.694026 -1.100235 0.214552
+v 2.624187 -0.936891 0.204915
+v 2.554348 -0.773548 0.195278
+v 2.484508 -0.610204 0.185641
+v 2.414669 -0.446860 0.176004
+v 2.344830 -0.283517 0.166367
+v 2.274990 -0.120173 0.156730
+v 2.205151 0.043171 0.147093
+v 2.135312 0.206514 0.137456
+v 2.065472 0.369858 0.127819
+v 1.995633 0.533202 0.118182
+v 1.925793 0.696545 0.108545
+v 1.855954 0.859889 0.098908
+v 1.786115 1.023233 0.089271
+v 1.716275 1.186576 0.079634
+v 1.646436 1.349920 0.069997
+v 1.576597 1.513264 0.060360
+v 1.506757 1.676607 0.050723
+v 1.436918 1.839951 0.041086
+v 1.367079 2.003294 0.031449
+v 1.297239 2.166638 0.021811
+v 1.227400 2.329982 0.012175
+v 1.157561 2.493325 0.002537
+v 1.087721 2.656669 -0.007100
+v 1.017882 2.820013 -0.016737
+v 0.948043 2.983356 -0.026374
+v 0.878203 3.146700 -0.036011
+v 0.808364 3.310044 -0.045648
+v 0.738524 3.473387 -0.055285
+v 0.668685 3.636731 -0.064922
+v 0.598846 3.800074 -0.074559
+v 0.529006 3.963418 -0.084196
+v 0.459167 4.126763 -0.093833
+v 0.389327 4.290105 -0.103470
+v 0.319488 4.453450 -0.113107
+v 0.249648 4.616793 -0.122744
+v 2.927488 -1.193951 0.218587
+v 2.857649 -1.030607 0.208950
+v 2.787809 -0.867264 0.199313
+v 2.717970 -0.703920 0.189676
+v 2.648130 -0.540576 0.180039
+v 2.578291 -0.377233 0.170402
+v 2.508452 -0.213889 0.160765
+v 2.438612 -0.050545 0.151128
+v 2.368773 0.112799 0.141491
+v 2.298934 0.276142 0.131854
+v 2.229095 0.439486 0.122217
+v 2.159255 0.602829 0.112580
+v 2.089416 0.766173 0.102943
+v 2.019576 0.929517 0.093306
+v 1.949737 1.092860 0.083669
+v 1.879898 1.256204 0.074032
+v 1.810058 1.419548 0.064395
+v 1.740219 1.582891 0.054758
+v 1.670380 1.746235 0.045121
+v 1.600540 1.909578 0.035484
+v 1.530701 2.072922 0.025846
+v 1.460862 2.236266 0.016210
+v 1.391022 2.399609 0.006572
+v 1.321183 2.562953 -0.003065
+v 1.251343 2.726297 -0.012702
+v 1.181504 2.889640 -0.022339
+v 1.111665 3.052984 -0.031976
+v 1.041825 3.216328 -0.041613
+v 0.971986 3.379672 -0.051250
+v 0.902147 3.543015 -0.060887
+v 0.832307 3.706359 -0.070524
+v 0.762468 3.869703 -0.080161
+v 0.692628 4.033046 -0.089798
+v 0.622789 4.196391 -0.099435
+v 0.552949 4.359733 -0.109072
+v 0.483110 4.523077 -0.118709
+v 0.413270 4.686420 -0.128346
+v 3.160949 -1.287667 0.222622
+v 3.091110 -1.124323 0.212985
+v 3.021271 -0.960980 0.203348
+v 2.951431 -0.797636 0.193711
+v 2.881592 -0.634292 0.184074
+v 2.811752 -0.470948 0.174437
+v 2.741913 -0.307605 0.164800
+v 2.672074 -0.144261 0.155163
+v 2.602234 0.019083 0.145526
+v 2.532395 0.182426 0.135889
+v 2.462556 0.345770 0.126252
+v 2.392716 0.509114 0.116615
+v 2.322877 0.672457 0.106978
+v 2.253038 0.835801 0.097341
+v 2.183198 0.999145 0.087704
+v 2.113359 1.162488 0.078067
+v 2.043519 1.325832 0.068430
+v 1.973680 1.489176 0.058793
+v 1.903841 1.652519 0.049156
+v 1.834001 1.815863 0.039519
+v 1.764162 1.979206 0.029881
+v 1.694323 2.142550 0.020245
+v 1.624483 2.305894 0.010607
+v 1.554644 2.469237 0.000970
+v 1.484805 2.632581 -0.008667
+v 1.414965 2.795925 -0.018304
+v 1.345126 2.959268 -0.027941
+v 1.275287 3.122612 -0.037578
+v 1.205447 3.285956 -0.047215
+v 1.135608 3.449299 -0.056852
+v 1.065768 3.612643 -0.066489
+v 0.995929 3.775987 -0.076126
+v 0.926090 3.939330 -0.085763
+v 0.856250 4.102675 -0.095400
+v 0.786411 4.266018 -0.105037
+v 0.716572 4.429361 -0.114674
+v 0.646732 4.592705 -0.124311
+v 0.576893 4.756048 -0.133948
+v 3.394411 -1.381383 0.226657
+v 3.324571 -1.218039 0.217020
+v 3.254732 -1.054695 0.207383
+v 3.184893 -0.891352 0.197746
+v 3.115053 -0.728008 0.188109
+v 3.045214 -0.564664 0.178472
+v 2.975374 -0.401321 0.168835
+v 2.905535 -0.237977 0.159198
+v 2.835696 -0.074633 0.149561
+v 2.765857 0.088711 0.139924
+v 2.696017 0.252054 0.130287
+v 2.626178 0.415398 0.120650
+v 2.556339 0.578741 0.111013
+v 2.486499 0.742085 0.101376
+v 2.416660 0.905429 0.091739
+v 2.346820 1.068772 0.082102
+v 2.276981 1.232116 0.072465
+v 2.207142 1.395460 0.062828
+v 2.137302 1.558803 0.053190
+v 2.067463 1.722147 0.043554
+v 1.997624 1.885490 0.033916
+v 1.927784 2.048834 0.024279
+v 1.857945 2.212178 0.014642
+v 1.788106 2.375521 0.005005
+v 1.718266 2.538865 -0.004632
+v 1.648427 2.702209 -0.014269
+v 1.578587 2.865552 -0.023906
+v 1.508748 3.028896 -0.033543
+v 1.438909 3.192240 -0.043180
+v 1.369069 3.355584 -0.052817
+v 1.299230 3.518927 -0.062454
+v 1.229391 3.682271 -0.072091
+v 1.159551 3.845615 -0.081728
+v 1.089712 4.008958 -0.091365
+v 1.019872 4.172303 -0.101002
+v 0.950033 4.335646 -0.110639
+v 0.880193 4.498990 -0.120276
+v 0.810354 4.662333 -0.129913
+v 0.740515 4.825676 -0.139550
+v 3.627872 -1.475098 0.230692
+v 3.558033 -1.311755 0.221055
+v 3.488194 -1.148411 0.211418
+v 3.418354 -0.985067 0.201781
+v 3.348515 -0.821724 0.192144
+v 3.278676 -0.658380 0.182507
+v 3.208836 -0.495036 0.172870
+v 3.138997 -0.331693 0.163233
+v 3.069157 -0.168349 0.153596
+v 2.999318 -0.005005 0.143959
+v 2.929479 0.158338 0.134322
+v 2.859639 0.321682 0.124685
+v 2.789800 0.485026 0.115048
+v 2.719961 0.648369 0.105411
+v 2.650121 0.811713 0.095774
+v 2.580282 0.975057 0.086137
+v 2.510442 1.138400 0.076500
+v 2.440603 1.301744 0.066863
+v 2.370764 1.465088 0.057225
+v 2.300925 1.628431 0.047589
+v 2.231085 1.791775 0.037951
+v 2.161246 1.955118 0.028314
+v 2.091406 2.118462 0.018677
+v 2.021567 2.281806 0.009040
+v 1.951728 2.445150 -0.000597
+v 1.881888 2.608493 -0.010234
+v 1.812049 2.771837 -0.019871
+v 1.742210 2.935180 -0.029508
+v 1.672370 3.098524 -0.039145
+v 1.602531 3.261868 -0.048782
+v 1.532691 3.425211 -0.058419
+v 1.462852 3.588555 -0.068056
+v 1.393013 3.751899 -0.077693
+v 1.323173 3.915242 -0.087330
+v 1.253334 4.078587 -0.096967
+v 1.183494 4.241930 -0.106604
+v 1.113655 4.405274 -0.116241
+v 1.043816 4.568617 -0.125878
+v 0.973976 4.731961 -0.135515
+v 0.904137 4.895304 -0.145152
+v 3.861333 -1.568815 0.234727
+v 3.791494 -1.405471 0.225090
+v 3.721655 -1.242127 0.215453
+v 3.651815 -1.078783 0.205816
+v 3.581976 -0.915440 0.196179
+v 3.512137 -0.752096 0.186542
+v 3.442297 -0.588752 0.176905
+v 3.372458 -0.425409 0.167268
+v 3.302619 -0.262065 0.157631
+v 3.232779 -0.098721 0.147994
+v 3.162940 0.064623 0.138357
+v 3.093101 0.227966 0.128720
+v 3.023261 0.391310 0.119083
+v 2.953422 0.554654 0.109446
+v 2.883583 0.717997 0.099809
+v 2.813743 0.881341 0.090172
+v 2.743904 1.044684 0.080535
+v 2.674064 1.208028 0.070898
+v 2.604225 1.371372 0.061260
+v 2.534386 1.534715 0.051624
+v 2.464546 1.698059 0.041986
+v 2.394707 1.861402 0.032349
+v 2.324868 2.024746 0.022712
+v 2.255028 2.188090 0.013075
+v 2.185189 2.351433 0.003438
+v 2.115350 2.514777 -0.006199
+v 2.045510 2.678120 -0.015836
+v 1.975671 2.841465 -0.025473
+v 1.905831 3.004808 -0.035110
+v 1.835992 3.168152 -0.044747
+v 1.766153 3.331496 -0.054384
+v 1.696313 3.494839 -0.064021
+v 1.626474 3.658183 -0.073658
+v 1.556635 3.821527 -0.083295
+v 1.486795 3.984870 -0.092932
+v 1.416956 4.148214 -0.102569
+v 1.347116 4.311558 -0.112206
+v 1.277277 4.474902 -0.121843
+v 1.207438 4.638245 -0.131480
+v 1.137598 4.801589 -0.141117
+v 1.067759 4.964931 -0.150754
+v 4.094795 -1.662530 0.238762
+v 4.024956 -1.499186 0.229125
+v 3.955116 -1.335843 0.219488
+v 3.885277 -1.172499 0.209851
+v 3.815438 -1.009155 0.200214
+v 3.745598 -0.845812 0.190577
+v 3.675759 -0.682468 0.180940
+v 3.605919 -0.519124 0.171303
+v 3.536080 -0.355781 0.161666
+v 3.466241 -0.192437 0.152029
+v 3.396401 -0.029093 0.142392
+v 3.326562 0.134250 0.132755
+v 3.256723 0.297594 0.123118
+v 3.186883 0.460938 0.113481
+v 3.117044 0.624281 0.103844
+v 3.047205 0.787625 0.094207
+v 2.977365 0.950969 0.084570
+v 2.907526 1.114312 0.074933
+v 2.837687 1.277656 0.065295
+v 2.767847 1.440999 0.055659
+v 2.698008 1.604343 0.046021
+v 2.628169 1.767687 0.036384
+v 2.558329 1.931030 0.026747
+v 2.488490 2.094374 0.017110
+v 2.418651 2.257718 0.007473
+v 2.348811 2.421061 -0.002164
+v 2.278972 2.584405 -0.011801
+v 2.209132 2.747748 -0.021438
+v 2.139293 2.911092 -0.031075
+v 2.069454 3.074436 -0.040712
+v 1.999614 3.237780 -0.050349
+v 1.929775 3.401124 -0.059986
+v 1.859936 3.564467 -0.069623
+v 1.790096 3.727811 -0.079260
+v 1.720257 3.891155 -0.088897
+v 1.650417 4.054498 -0.098534
+v 1.580578 4.217842 -0.108171
+v 1.510738 4.381186 -0.117808
+v 1.440899 4.544529 -0.127445
+v 1.371060 4.707873 -0.137082
+v 1.301220 4.871216 -0.146720
+v 1.231381 5.034559 -0.156357
+v 4.328257 -1.756246 0.242797
+v 4.258417 -1.592903 0.233160
+v 4.188578 -1.429559 0.223523
+v 4.118738 -1.266215 0.213886
+v 4.048899 -1.102871 0.204249
+v 3.979060 -0.939528 0.194612
+v 3.909220 -0.776184 0.184975
+v 3.839381 -0.612840 0.175338
+v 3.769542 -0.449497 0.165701
+v 3.699702 -0.286153 0.156064
+v 3.629863 -0.122809 0.146427
+v 3.560024 0.040535 0.136790
+v 3.490184 0.203878 0.127153
+v 3.420345 0.367222 0.117516
+v 3.350505 0.530566 0.107879
+v 3.280666 0.693909 0.098242
+v 3.210827 0.857253 0.088605
+v 3.140987 1.020596 0.078968
+v 3.071148 1.183940 0.069330
+v 3.001309 1.347284 0.059694
+v 2.931469 1.510627 0.050056
+v 2.861630 1.673971 0.040419
+v 2.791791 1.837314 0.030782
+v 2.721951 2.000658 0.021145
+v 2.652112 2.164002 0.011508
+v 2.582273 2.327345 0.001871
+v 2.512433 2.490689 -0.007766
+v 2.442594 2.654033 -0.017403
+v 2.372755 2.817376 -0.027040
+v 2.302915 2.980720 -0.036677
+v 2.233076 3.144064 -0.046314
+v 2.163237 3.307407 -0.055951
+v 2.093397 3.470751 -0.065588
+v 2.023558 3.634095 -0.075225
+v 1.953718 3.797439 -0.084862
+v 1.883879 3.960782 -0.094499
+v 1.814040 4.124126 -0.104136
+v 1.744200 4.287470 -0.113773
+v 1.674361 4.450814 -0.123410
+v 1.604521 4.614157 -0.133048
+v 1.534682 4.777501 -0.142685
+v 1.464842 4.940844 -0.152322
+v 1.395003 5.104187 -0.161959
+v 4.561718 -1.849962 0.246832
+v 4.491879 -1.686618 0.237195
+v 4.422039 -1.523275 0.227558
+v 4.352200 -1.359931 0.217921
+v 4.282360 -1.196587 0.208284
+v 4.212521 -1.033243 0.198647
+v 4.142681 -0.869900 0.189010
+v 4.072842 -0.706556 0.179373
+v 4.003003 -0.543212 0.169736
+v 3.933163 -0.379869 0.160099
+v 3.863324 -0.216525 0.150462
+v 3.793484 -0.053181 0.140825
+v 3.723645 0.110162 0.131188
+v 3.653806 0.273506 0.121551
+v 3.583966 0.436850 0.111914
+v 3.514127 0.600194 0.102277
+v 3.444288 0.763537 0.092639
+v 3.374448 0.926881 0.083003
+v 3.304609 1.090224 0.073365
+v 3.234770 1.253568 0.063729
+v 3.164930 1.416912 0.054091
+v 3.095091 1.580255 0.044454
+v 3.025252 1.743599 0.034817
+v 2.955412 1.906943 0.025180
+v 2.885573 2.070286 0.015543
+v 2.815734 2.233629 0.005906
+v 2.745894 2.396973 -0.003731
+v 2.676055 2.560317 -0.013368
+v 2.606216 2.723661 -0.023005
+v 2.536376 2.887004 -0.032642
+v 2.466537 3.050348 -0.042279
+v 2.396698 3.213691 -0.051916
+v 2.326858 3.377035 -0.061553
+v 2.257019 3.540379 -0.071190
+v 2.187180 3.703722 -0.080827
+v 2.117340 3.867067 -0.090464
+v 2.047501 4.030410 -0.100101
+v 1.977661 4.193754 -0.109738
+v 1.907822 4.357098 -0.119375
+v 1.837982 4.520442 -0.129013
+v 1.768143 4.683785 -0.138650
+v 1.698304 4.847129 -0.148287
+v 1.628464 5.010472 -0.157924
+v 1.558625 5.173815 -0.167561
+v 4.795178 -1.943678 0.250867
+v 4.725339 -1.780334 0.241230
+v 4.655500 -1.616990 0.231593
+v 4.585661 -1.453647 0.221956
+v 4.515821 -1.290303 0.212319
+v 4.445982 -1.126959 0.202682
+v 4.376143 -0.963615 0.193045
+v 4.306303 -0.800272 0.183408
+v 4.236464 -0.636928 0.173771
+v 4.166625 -0.473584 0.164134
+v 4.096786 -0.310241 0.154497
+v 4.026946 -0.146897 0.144860
+v 3.957106 0.016446 0.135223
+v 3.887267 0.179790 0.125586
+v 3.817428 0.343134 0.115949
+v 3.747588 0.506478 0.106312
+v 3.677749 0.669821 0.096674
+v 3.607910 0.833165 0.087038
+v 3.538070 0.996508 0.077400
+v 3.468231 1.159852 0.067763
+v 3.398391 1.323196 0.058126
+v 3.328552 1.486539 0.048489
+v 3.258713 1.649883 0.038852
+v 3.188874 1.813227 0.029215
+v 3.119034 1.976570 0.019578
+v 3.049195 2.139914 0.009941
+v 2.979356 2.303257 0.000304
+v 2.909516 2.466601 -0.009333
+v 2.839677 2.629944 -0.018970
+v 2.769838 2.793288 -0.028607
+v 2.699998 2.956631 -0.038244
+v 2.630159 3.119976 -0.047881
+v 2.560319 3.283319 -0.057518
+v 2.490480 3.446663 -0.067155
+v 2.420641 3.610007 -0.076792
+v 2.350801 3.773350 -0.086429
+v 2.280962 3.936694 -0.096066
+v 2.211123 4.100038 -0.105703
+v 2.141283 4.263381 -0.115340
+v 2.071444 4.426725 -0.124978
+v 2.001605 4.590069 -0.134615
+v 1.931765 4.753413 -0.144252
+v 1.861926 4.916757 -0.153889
+v 1.792086 5.080100 -0.163526
+v 1.722247 5.243443 -0.173163
+v 5.028641 -2.037393 0.254902
+v 4.958801 -1.874050 0.245265
+v 4.888962 -1.710706 0.235628
+v 4.819122 -1.547362 0.225991
+v 4.749283 -1.384019 0.216354
+v 4.679443 -1.220675 0.206717
+v 4.609604 -1.057331 0.197080
+v 4.539764 -0.893988 0.187443
+v 4.469925 -0.730644 0.177806
+v 4.400086 -0.567300 0.168169
+v 4.330247 -0.403957 0.158532
+v 4.260407 -0.240613 0.148895
+v 4.190568 -0.077269 0.139258
+v 4.120728 0.086074 0.129621
+v 4.050889 0.249418 0.119984
+v 3.981050 0.412762 0.110347
+v 3.911211 0.576105 0.100709
+v 3.841371 0.739449 0.091073
+v 3.771532 0.902793 0.081435
+v 3.701692 1.066136 0.071798
+v 3.631853 1.229480 0.062161
+v 3.562014 1.392824 0.052524
+v 3.492174 1.556167 0.042887
+v 3.422335 1.719511 0.033250
+v 3.352496 1.882854 0.023613
+v 3.282656 2.046198 0.013976
+v 3.212817 2.209542 0.004339
+v 3.142978 2.372885 -0.005298
+v 3.073138 2.536229 -0.014935
+v 3.003299 2.699573 -0.024572
+v 2.933460 2.862916 -0.034209
+v 2.863620 3.026260 -0.043846
+v 2.793781 3.189603 -0.053483
+v 2.723942 3.352947 -0.063120
+v 2.654102 3.516291 -0.072757
+v 2.584263 3.679635 -0.082394
+v 2.514423 3.842979 -0.092031
+v 2.444584 4.006322 -0.101668
+v 2.374745 4.169666 -0.111305
+v 2.304905 4.333009 -0.120943
+v 2.235066 4.496353 -0.130580
+v 2.165227 4.659697 -0.140217
+v 2.095387 4.823040 -0.149854
+v 2.025548 4.986385 -0.159491
+v 1.955708 5.149727 -0.169128
+v 1.885869 5.313070 -0.178765
+v 5.262101 -2.131109 0.258937
+v 5.192262 -1.967766 0.249300
+v 5.122422 -1.804422 0.239663
+v 5.052583 -1.641078 0.230026
+v 4.982744 -1.477734 0.220389
+v 4.912905 -1.314391 0.210752
+v 4.843065 -1.151047 0.201115
+v 4.773226 -0.987703 0.191478
+v 4.703386 -0.824360 0.181841
+v 4.633547 -0.661016 0.172204
+v 4.563707 -0.497672 0.162567
+v 4.493869 -0.334329 0.152930
+v 4.424029 -0.170985 0.143293
+v 4.354190 -0.007642 0.133656
+v 4.284350 0.155702 0.124019
+v 4.214511 0.319046 0.114382
+v 4.144671 0.482390 0.104744
+v 4.074832 0.645733 0.095108
+v 4.004992 0.809077 0.085470
+v 3.935153 0.972420 0.075833
+v 3.865314 1.135764 0.066196
+v 3.795475 1.299108 0.056559
+v 3.725635 1.462451 0.046922
+v 3.655796 1.625795 0.037285
+v 3.585957 1.789138 0.027648
+v 3.516117 1.952482 0.018011
+v 3.446278 2.115826 0.008374
+v 3.376439 2.279169 -0.001263
+v 3.306599 2.442513 -0.010900
+v 3.236760 2.605856 -0.020537
+v 3.166921 2.769200 -0.030174
+v 3.097081 2.932544 -0.039811
+v 3.027242 3.095887 -0.049448
+v 2.957403 3.259231 -0.059085
+v 2.887563 3.422575 -0.068722
+v 2.817724 3.585918 -0.078359
+v 2.747885 3.749262 -0.087996
+v 2.678045 3.912606 -0.097633
+v 2.608206 4.075950 -0.107270
+v 2.538366 4.239294 -0.116908
+v 2.468527 4.402637 -0.126545
+v 2.398688 4.565981 -0.136182
+v 2.328848 4.729325 -0.145819
+v 2.259009 4.892668 -0.155456
+v 2.189170 5.056013 -0.165093
+v 2.119330 5.219355 -0.174730
+v 2.049491 5.382698 -0.184367
+v 5.495563 -2.224826 0.262972
+v 5.425723 -2.061481 0.253335
+v 5.355885 -1.898138 0.243698
+v 5.286045 -1.734794 0.234061
+v 5.216206 -1.571451 0.224424
+v 5.146366 -1.408107 0.214787
+v 5.076527 -1.244763 0.205150
+v 5.006687 -1.081420 0.195513
+v 4.936848 -0.918076 0.185876
+v 4.867008 -0.754732 0.176239
+v 4.797169 -0.591388 0.166602
+v 4.727330 -0.428045 0.156965
+v 4.657491 -0.264701 0.147328
+v 4.587651 -0.101357 0.137691
+v 4.517812 0.061986 0.128054
+v 4.447972 0.225330 0.118417
+v 4.378133 0.388674 0.108779
+v 4.308293 0.552017 0.099143
+v 4.238455 0.715361 0.089505
+v 4.168615 0.878705 0.079868
+v 4.098776 1.042048 0.070231
+v 4.028936 1.205392 0.060594
+v 3.959097 1.368735 0.050957
+v 3.889257 1.532079 0.041320
+v 3.819418 1.695423 0.031683
+v 3.749579 1.858766 0.022046
+v 3.679739 2.022110 0.012409
+v 3.609900 2.185454 0.002772
+v 3.540061 2.348797 -0.006865
+v 3.470222 2.512141 -0.016502
+v 3.400382 2.675484 -0.026139
+v 3.330543 2.838828 -0.035776
+v 3.260704 3.002172 -0.045413
+v 3.190864 3.165515 -0.055050
+v 3.121025 3.328859 -0.064687
+v 3.051185 3.492203 -0.074324
+v 2.981346 3.655546 -0.083961
+v 2.911507 3.818890 -0.093598
+v 2.841667 3.982234 -0.103236
+v 2.771828 4.145578 -0.112873
+v 2.701989 4.308921 -0.122510
+v 2.632149 4.472265 -0.132147
+v 2.562310 4.635609 -0.141784
+v 2.492471 4.798953 -0.151421
+v 2.422631 4.962296 -0.161058
+v 2.352792 5.125640 -0.170695
+v 2.282953 5.288983 -0.180332
+v 2.213113 5.452327 -0.189969
+v 5.729023 -2.318541 0.267007
+v 5.659184 -2.155197 0.257370
+v 5.589345 -1.991854 0.247733
+v 5.519506 -1.828510 0.238096
+v 5.449666 -1.665166 0.228459
+v 5.379827 -1.501822 0.218822
+v 5.309987 -1.338479 0.209185
+v 5.240148 -1.175135 0.199548
+v 5.170308 -1.011791 0.189911
+v 5.100470 -0.848448 0.180274
+v 5.030630 -0.685104 0.170637
+v 4.960791 -0.521760 0.161000
+v 4.890951 -0.358416 0.151363
+v 4.821112 -0.195073 0.141726
+v 4.751272 -0.031729 0.132089
+v 4.681433 0.131614 0.122452
+v 4.611594 0.294958 0.112814
+v 4.541755 0.458302 0.103178
+v 4.471915 0.621645 0.093540
+v 4.402076 0.784989 0.083903
+v 4.332236 0.948332 0.074266
+v 4.262397 1.111676 0.064629
+v 4.192557 1.275020 0.054992
+v 4.122719 1.438363 0.045355
+v 4.052879 1.601707 0.035718
+v 3.983040 1.765051 0.026081
+v 3.913200 1.928394 0.016444
+v 3.843361 2.091738 0.006807
+v 3.773521 2.255081 -0.002830
+v 3.703682 2.418425 -0.012467
+v 3.633843 2.581769 -0.022104
+v 3.564003 2.745112 -0.031741
+v 3.494164 2.908456 -0.041378
+v 3.424325 3.071799 -0.051015
+v 3.354486 3.235143 -0.060652
+v 3.284646 3.398487 -0.070289
+v 3.214807 3.561830 -0.079926
+v 3.144968 3.725174 -0.089563
+v 3.075128 3.888518 -0.099200
+v 3.005289 4.051861 -0.108838
+v 2.935449 4.215206 -0.118475
+v 2.865610 4.378549 -0.128112
+v 2.795771 4.541893 -0.137749
+v 2.725931 4.705236 -0.147386
+v 2.656092 4.868580 -0.157023
+v 2.586253 5.031924 -0.166660
+v 2.516413 5.195268 -0.176297
+v 2.446574 5.358611 -0.185934
+v 2.376735 5.521955 -0.195571
+v -2.218616 -5.893647 0.551145
+v -2.054993 -5.824019 0.545543
+v -2.288455 -5.730304 0.541508
+v -1.891371 -5.754392 0.539941
+v -2.124833 -5.660676 0.535906
+v -2.358294 -5.566959 0.531871
+v -1.727749 -5.684764 0.534339
+v -1.961210 -5.591048 0.530304
+v -2.194672 -5.497332 0.526269
+v -2.428133 -5.403617 0.522234
+v -1.564127 -5.615136 0.528737
+v -1.797588 -5.521420 0.524702
+v -2.031050 -5.427704 0.520667
+v -2.264511 -5.333989 0.516632
+v -2.497972 -5.240272 0.512597
+v -1.400505 -5.545508 0.523135
+v -1.633966 -5.451793 0.519100
+v -1.867428 -5.358076 0.515065
+v -2.100889 -5.264361 0.511030
+v -2.334351 -5.170644 0.506995
+v -2.567812 -5.076930 0.502960
+v -1.236883 -5.475881 0.517533
+v -1.470344 -5.382164 0.513498
+v -1.703806 -5.288448 0.509463
+v -1.937267 -5.194733 0.505428
+v -2.170728 -5.101017 0.501393
+v -2.404190 -5.007302 0.497358
+v -2.637651 -4.913586 0.493323
+v -1.073261 -5.406252 0.511930
+v -1.306722 -5.312536 0.507895
+v -1.540184 -5.218821 0.503860
+v -1.773645 -5.125105 0.499825
+v -2.007106 -5.031389 0.495791
+v -2.240568 -4.937673 0.491756
+v -2.474029 -4.843958 0.487721
+v -2.707490 -4.750243 0.483686
+v -0.909639 -5.336624 0.506329
+v -1.143100 -5.242908 0.502294
+v -1.376562 -5.149193 0.498259
+v -1.610023 -5.055477 0.494224
+v -1.843484 -4.961761 0.490189
+v -2.076945 -4.868045 0.486154
+v -2.310407 -4.774330 0.482119
+v -2.543869 -4.680614 0.478084
+v -2.777330 -4.586899 0.474049
+v -0.746017 -5.266996 0.500726
+v -0.979478 -5.173281 0.496691
+v -1.212940 -5.079565 0.492656
+v -1.446401 -4.985850 0.488621
+v -1.679862 -4.892134 0.484586
+v -1.913324 -4.798418 0.480551
+v -2.146785 -4.704702 0.476516
+v -2.380247 -4.610986 0.472481
+v -2.613708 -4.517271 0.468446
+v -2.847169 -4.423555 0.464411
+v -0.582395 -5.197369 0.495124
+v -0.815856 -5.103653 0.491089
+v -1.049317 -5.009937 0.487054
+v -1.282779 -4.916221 0.483019
+v -1.516240 -4.822505 0.478984
+v -1.749701 -4.728789 0.474949
+v -1.983163 -4.635074 0.470914
+v -2.216624 -4.541358 0.466880
+v -2.450086 -4.447642 0.462845
+v -2.683547 -4.353927 0.458810
+v -2.917009 -4.260211 0.454775
+v -0.418772 -5.127741 0.489522
+v -0.652234 -5.034025 0.485487
+v -0.885695 -4.940310 0.481452
+v -1.119157 -4.846593 0.477417
+v -1.352618 -4.752878 0.473382
+v -1.586080 -4.659162 0.469347
+v -1.819541 -4.565446 0.465312
+v -2.053002 -4.471730 0.461277
+v -2.286463 -4.378014 0.457242
+v -2.519925 -4.284298 0.453207
+v -2.753386 -4.190583 0.449172
+v -2.986848 -4.096868 0.445138
+v -0.255151 -5.058113 0.483920
+v -0.488612 -4.964397 0.479885
+v -0.722073 -4.870682 0.475850
+v -0.955535 -4.776966 0.471815
+v -1.188996 -4.683250 0.467780
+v -1.422458 -4.589534 0.463745
+v -1.655919 -4.495819 0.459710
+v -1.889380 -4.402102 0.455675
+v -2.122842 -4.308386 0.451640
+v -2.356303 -4.214671 0.447605
+v -2.589765 -4.120955 0.443570
+v -2.823226 -4.027239 0.439535
+v -3.056687 -3.933524 0.435500
+v -0.091529 -4.988485 0.478318
+v -0.324990 -4.894770 0.474283
+v -0.558451 -4.801054 0.470248
+v -0.791913 -4.707338 0.466213
+v -1.025374 -4.613622 0.462178
+v -1.258836 -4.519907 0.458143
+v -1.492297 -4.426191 0.454108
+v -1.725758 -4.332475 0.450073
+v -1.959220 -4.238759 0.446038
+v -2.192681 -4.145043 0.442003
+v -2.426142 -4.051328 0.437968
+v -2.659604 -3.957612 0.433933
+v -2.893065 -3.863896 0.429899
+v -3.126527 -3.770180 0.425864
+v 0.072093 -4.918858 0.472716
+v -0.161368 -4.825142 0.468681
+v -0.394830 -4.731426 0.464646
+v -0.628291 -4.637710 0.460611
+v -0.861752 -4.543994 0.456576
+v -1.095214 -4.450279 0.452541
+v -1.328675 -4.356562 0.448506
+v -1.562136 -4.262847 0.444471
+v -1.795598 -4.169131 0.440436
+v -2.029059 -4.075416 0.436401
+v -2.262521 -3.981699 0.432366
+v -2.495982 -3.887984 0.428331
+v -2.729443 -3.794269 0.424296
+v -2.962905 -3.700552 0.420261
+v -3.196366 -3.606837 0.416226
+v 0.235715 -4.849230 0.467114
+v 0.002254 -4.755514 0.463079
+v -0.231208 -4.661798 0.459044
+v -0.464669 -4.568082 0.455009
+v -0.698130 -4.474367 0.450974
+v -0.931592 -4.380651 0.446939
+v -1.165053 -4.286934 0.442904
+v -1.398514 -4.193219 0.438869
+v -1.631976 -4.099504 0.434834
+v -1.865437 -4.005788 0.430799
+v -2.098898 -3.912072 0.426764
+v -2.332360 -3.818356 0.422729
+v -2.565821 -3.724640 0.418694
+v -2.799283 -3.630925 0.414659
+v -3.032744 -3.537209 0.410624
+v -3.266205 -3.443493 0.406589
+v 0.399337 -4.779602 0.461512
+v 0.165876 -4.685886 0.457477
+v -0.067586 -4.592171 0.453442
+v -0.301047 -4.498455 0.449407
+v -0.534508 -4.404739 0.445372
+v -0.767970 -4.311023 0.441337
+v -1.001431 -4.217307 0.437302
+v -1.234892 -4.123591 0.433267
+v -1.468354 -4.029876 0.429232
+v -1.701815 -3.936160 0.425197
+v -1.935277 -3.842444 0.421162
+v -2.168738 -3.748729 0.417127
+v -2.402199 -3.655013 0.413092
+v -2.635661 -3.561297 0.409057
+v -2.869122 -3.467582 0.405022
+v -3.102583 -3.373866 0.400987
+v -3.336045 -3.280150 0.396952
+v 0.562959 -4.709974 0.455910
+v 0.329498 -4.616258 0.451875
+v 0.096036 -4.522543 0.447840
+v -0.137425 -4.428827 0.443805
+v -0.370887 -4.335111 0.439770
+v -0.604348 -4.241395 0.435735
+v -0.837809 -4.147679 0.431700
+v -1.071271 -4.053964 0.427665
+v -1.304732 -3.960248 0.423630
+v -1.538193 -3.866532 0.419595
+v -1.771655 -3.772816 0.415560
+v -2.005116 -3.679101 0.411525
+v -2.238577 -3.585385 0.407490
+v -2.472039 -3.491669 0.403455
+v -2.705500 -3.397954 0.399420
+v -2.938962 -3.304238 0.395385
+v -3.172423 -3.210522 0.391350
+v -3.405884 -3.116806 0.387315
+v 0.726581 -4.640347 0.450308
+v 0.493120 -4.546630 0.446273
+v 0.259658 -4.452915 0.442238
+v 0.026197 -4.359199 0.438203
+v -0.207264 -4.265483 0.434168
+v -0.440726 -4.171768 0.430133
+v -0.674187 -4.078052 0.426098
+v -0.907648 -3.984335 0.422063
+v -1.141110 -3.890620 0.418028
+v -1.374571 -3.796905 0.413993
+v -1.608033 -3.703188 0.409958
+v -1.841494 -3.609473 0.405923
+v -2.074955 -3.515757 0.401888
+v -2.308417 -3.422041 0.397853
+v -2.541878 -3.328326 0.393818
+v -2.775339 -3.234610 0.389783
+v -3.008801 -3.140894 0.385748
+v -3.242262 -3.047179 0.381713
+v -3.475723 -2.953463 0.377678
+v 0.890203 -4.570719 0.444706
+v 0.656742 -4.477002 0.440671
+v 0.423280 -4.383287 0.436636
+v 0.189819 -4.289571 0.432601
+v -0.043642 -4.195856 0.428566
+v -0.277104 -4.102139 0.424531
+v -0.510565 -4.008424 0.420496
+v -0.744026 -3.914708 0.416461
+v -0.977488 -3.820992 0.412426
+v -1.210949 -3.727276 0.408391
+v -1.444410 -3.633561 0.404356
+v -1.677872 -3.539845 0.400321
+v -1.911333 -3.446129 0.396286
+v -2.144794 -3.352414 0.392251
+v -2.378256 -3.258698 0.388216
+v -2.611717 -3.164982 0.384181
+v -2.845179 -3.071266 0.380146
+v -3.078640 -2.977550 0.376111
+v -3.312101 -2.883835 0.372076
+v -3.545563 -2.790119 0.368041
+v 1.053825 -4.501091 0.439104
+v 0.820364 -4.407374 0.435069
+v 0.586903 -4.313660 0.431034
+v 0.353441 -4.219944 0.426999
+v 0.119980 -4.126228 0.422964
+v -0.113482 -4.032512 0.418929
+v -0.346943 -3.938796 0.414894
+v -0.580405 -3.845080 0.410859
+v -0.813866 -3.751364 0.406824
+v -1.047327 -3.657649 0.402789
+v -1.280789 -3.563933 0.398754
+v -1.514250 -3.470217 0.394719
+v -1.747711 -3.376501 0.390684
+v -1.981173 -3.282785 0.386649
+v -2.214634 -3.189070 0.382614
+v -2.448095 -3.095354 0.378579
+v -2.681557 -3.001638 0.374544
+v -2.915018 -2.907923 0.370509
+v -3.148480 -2.814207 0.366474
+v -3.381941 -2.720491 0.362439
+v -3.615402 -2.626775 0.358404
+v 1.217447 -4.431463 0.433502
+v 0.983986 -4.337747 0.429467
+v 0.750524 -4.244032 0.425432
+v 0.517063 -4.150316 0.421397
+v 0.283602 -4.056600 0.417362
+v 0.050140 -3.962884 0.413327
+v -0.183321 -3.869168 0.409292
+v -0.416783 -3.775452 0.405257
+v -0.650244 -3.681736 0.401222
+v -0.883705 -3.588021 0.397187
+v -1.117167 -3.494305 0.393152
+v -1.350628 -3.400589 0.389117
+v -1.584089 -3.306873 0.385082
+v -1.817551 -3.213157 0.381047
+v -2.051012 -3.119442 0.377012
+v -2.284473 -3.025727 0.372977
+v -2.517935 -2.932010 0.368942
+v -2.751396 -2.838295 0.364907
+v -2.984857 -2.744579 0.360872
+v -3.218319 -2.650863 0.356837
+v -3.451780 -2.557148 0.352802
+v -3.685241 -2.463431 0.348767
+v 1.381069 -4.361835 0.427900
+v 1.147608 -4.268119 0.423865
+v 0.914147 -4.174404 0.419830
+v 0.680685 -4.080688 0.415795
+v 0.447224 -3.986972 0.411760
+v 0.213762 -3.893256 0.407725
+v -0.019699 -3.799540 0.403690
+v -0.253161 -3.705824 0.399655
+v -0.486622 -3.612109 0.395620
+v -0.720084 -3.518393 0.391585
+v -0.953545 -3.424677 0.387550
+v -1.187006 -3.330961 0.383515
+v -1.420467 -3.237246 0.379480
+v -1.653929 -3.143530 0.375445
+v -1.887390 -3.049814 0.371410
+v -2.120852 -2.956098 0.367375
+v -2.354313 -2.862382 0.363340
+v -2.587774 -2.768667 0.359305
+v -2.821235 -2.674951 0.355270
+v -3.054697 -2.581235 0.351235
+v -3.288158 -2.487519 0.347200
+v -3.521620 -2.393804 0.343165
+v -3.755081 -2.300088 0.339130
+v 1.544691 -4.292208 0.422298
+v 1.311230 -4.198491 0.418263
+v 1.077768 -4.104776 0.414228
+v 0.844307 -4.011060 0.410193
+v 0.610846 -3.917344 0.406158
+v 0.377384 -3.823628 0.402123
+v 0.143923 -3.729912 0.398088
+v -0.089539 -3.636197 0.394053
+v -0.323000 -3.542481 0.390018
+v -0.556461 -3.448765 0.385983
+v -0.789923 -3.355049 0.381948
+v -1.023384 -3.261333 0.377913
+v -1.256845 -3.167618 0.373878
+v -1.490307 -3.073902 0.369843
+v -1.723768 -2.980186 0.365808
+v -1.957229 -2.886470 0.361773
+v -2.190691 -2.792754 0.357738
+v -2.424152 -2.699039 0.353703
+v -2.657614 -2.605323 0.349668
+v -2.891075 -2.511607 0.345633
+v -3.124536 -2.417892 0.341598
+v -3.357998 -2.324176 0.337563
+v -3.591459 -2.230460 0.333528
+v -3.824920 -2.136744 0.329493
+v 1.708313 -4.222580 0.416696
+v 1.474852 -4.128863 0.412661
+v 1.241390 -4.035148 0.408626
+v 1.007929 -3.941432 0.404591
+v 0.774468 -3.847716 0.400556
+v 0.541006 -3.754000 0.396521
+v 0.307545 -3.660285 0.392486
+v 0.074084 -3.566569 0.388451
+v -0.159378 -3.472853 0.384416
+v -0.392839 -3.379137 0.380381
+v -0.626301 -3.285421 0.376346
+v -0.859762 -3.191705 0.372311
+v -1.093223 -3.097989 0.368276
+v -1.326685 -3.004274 0.364241
+v -1.560146 -2.910558 0.360206
+v -1.793607 -2.816843 0.356171
+v -2.027069 -2.723127 0.352136
+v -2.260530 -2.629411 0.348101
+v -2.493991 -2.535695 0.344066
+v -2.727453 -2.441979 0.340031
+v -2.960914 -2.348264 0.335996
+v -3.194375 -2.254548 0.331961
+v -3.427837 -2.160832 0.327926
+v -3.661298 -2.067116 0.323891
+v -3.894759 -1.973400 0.319856
+v 1.871935 -4.152952 0.411094
+v 1.638474 -4.059236 0.407059
+v 1.405012 -3.965520 0.403024
+v 1.171551 -3.871805 0.398989
+v 0.938090 -3.778089 0.394954
+v 0.704628 -3.684372 0.390919
+v 0.471167 -3.590657 0.386884
+v 0.237706 -3.496941 0.382849
+v 0.004244 -3.403225 0.378814
+v -0.229217 -3.309509 0.374779
+v -0.462679 -3.215794 0.370744
+v -0.696140 -3.122078 0.366709
+v -0.929602 -3.028362 0.362674
+v -1.163063 -2.934646 0.358639
+v -1.396524 -2.840931 0.354604
+v -1.629985 -2.747215 0.350569
+v -1.863447 -2.653499 0.346534
+v -2.096908 -2.559783 0.342499
+v -2.330369 -2.466068 0.338464
+v -2.563831 -2.372352 0.334429
+v -2.797292 -2.278636 0.330394
+v -3.030753 -2.184920 0.326359
+v -3.264215 -2.091204 0.322324
+v -3.497676 -1.997488 0.318289
+v -3.731138 -1.903773 0.314254
+v -3.964599 -1.810057 0.310219
+v 2.035557 -4.083324 0.405492
+v 1.802096 -3.989609 0.401457
+v 1.568634 -3.895892 0.397422
+v 1.335173 -3.802177 0.393387
+v 1.101712 -3.708461 0.389352
+v 0.868250 -3.614745 0.385317
+v 0.634789 -3.521029 0.381282
+v 0.401328 -3.427313 0.377247
+v 0.167866 -3.333597 0.373212
+v -0.065595 -3.239882 0.369177
+v -0.299057 -3.146165 0.365142
+v -0.532518 -3.052450 0.361107
+v -0.765979 -2.958734 0.357072
+v -0.999441 -2.865018 0.353036
+v -1.232902 -2.771303 0.349001
+v -1.466363 -2.677587 0.344966
+v -1.699825 -2.583871 0.340932
+v -1.933286 -2.490155 0.336897
+v -2.166747 -2.396440 0.332862
+v -2.400209 -2.302724 0.328827
+v -2.633670 -2.209008 0.324792
+v -2.867131 -2.115292 0.320757
+v -3.100593 -2.021576 0.316722
+v -3.334054 -1.927860 0.312687
+v -3.567516 -1.834145 0.308652
+v -3.800977 -1.740429 0.304617
+v -4.034438 -1.646713 0.300582
+v 2.199179 -4.013697 0.399889
+v 1.965718 -3.919981 0.395854
+v 1.732256 -3.826265 0.391819
+v 1.498795 -3.732549 0.387784
+v 1.265334 -3.638833 0.383749
+v 1.031872 -3.545117 0.379714
+v 0.798411 -3.451401 0.375679
+v 0.564950 -3.357686 0.371644
+v 0.331488 -3.263969 0.367610
+v 0.098027 -3.170254 0.363575
+v -0.135435 -3.076538 0.359540
+v -0.368896 -2.982822 0.355505
+v -0.602357 -2.889106 0.351470
+v -0.835819 -2.795390 0.347435
+v -1.069280 -2.701675 0.343400
+v -1.302741 -2.607959 0.339365
+v -1.536203 -2.514243 0.335330
+v -1.769664 -2.420527 0.331295
+v -2.003125 -2.326812 0.327260
+v -2.236587 -2.233096 0.323225
+v -2.470048 -2.139380 0.319190
+v -2.703509 -2.045664 0.315155
+v -2.936971 -1.951948 0.311120
+v -3.170432 -1.858232 0.307085
+v -3.403893 -1.764517 0.303050
+v -3.637355 -1.670801 0.299015
+v -3.870816 -1.577085 0.294980
+v -4.104278 -1.483369 0.290945
+v 2.362801 -3.944069 0.394287
+v 2.129340 -3.850353 0.390253
+v 1.895878 -3.756637 0.386218
+v 1.662417 -3.662921 0.382183
+v 1.428956 -3.569205 0.378148
+v 1.195494 -3.475489 0.374113
+v 0.962033 -3.381773 0.370078
+v 0.728572 -3.288058 0.366043
+v 0.495110 -3.194342 0.362008
+v 0.261649 -3.100626 0.357973
+v 0.028187 -3.006910 0.353938
+v -0.205274 -2.913194 0.349903
+v -0.438735 -2.819478 0.345867
+v -0.672197 -2.725763 0.341832
+v -0.905658 -2.632047 0.337797
+v -1.139120 -2.538331 0.333762
+v -1.372581 -2.444616 0.329727
+v -1.606042 -2.350899 0.325692
+v -1.839504 -2.257183 0.321657
+v -2.072965 -2.163467 0.317622
+v -2.306426 -2.069752 0.313587
+v -2.539887 -1.976036 0.309552
+v -2.773349 -1.882320 0.305517
+v -3.006810 -1.788605 0.301483
+v -3.240271 -1.694889 0.297448
+v -3.473733 -1.601173 0.293413
+v -3.707194 -1.507457 0.289378
+v -3.940656 -1.413742 0.285343
+v -4.174116 -1.320026 0.281308
+v 2.526423 -3.874441 0.388685
+v 2.292962 -3.780725 0.384650
+v 2.059500 -3.687009 0.380615
+v 1.826039 -3.593294 0.376580
+v 1.592578 -3.499577 0.372545
+v 1.359116 -3.405861 0.368510
+v 1.125655 -3.312146 0.364475
+v 0.892194 -3.218430 0.360440
+v 0.658732 -3.124714 0.356405
+v 0.425271 -3.030998 0.352371
+v 0.191809 -2.937282 0.348336
+v -0.041652 -2.843566 0.344300
+v -0.275113 -2.749850 0.340265
+v -0.508575 -2.656135 0.336230
+v -0.742036 -2.562419 0.332195
+v -0.975497 -2.468703 0.328160
+v -1.208959 -2.374988 0.324125
+v -1.442420 -2.281271 0.320090
+v -1.675881 -2.187556 0.316055
+v -1.909343 -2.093840 0.312021
+v -2.142804 -2.000124 0.307986
+v -2.376266 -1.906408 0.303951
+v -2.609727 -1.812692 0.299916
+v -2.843188 -1.718977 0.295881
+v -3.076649 -1.625261 0.291846
+v -3.310111 -1.531545 0.287811
+v -3.543572 -1.437829 0.283776
+v -3.777034 -1.344114 0.279741
+v -4.010494 -1.250398 0.275706
+v -4.243956 -1.156682 0.271671
+v 2.690045 -3.804814 0.383083
+v 2.456584 -3.711097 0.379048
+v 2.223123 -3.617381 0.375013
+v 1.989661 -3.523665 0.370978
+v 1.756200 -3.429949 0.366943
+v 1.522738 -3.336234 0.362908
+v 1.289277 -3.242518 0.358873
+v 1.055816 -3.148802 0.354838
+v 0.822354 -3.055086 0.350803
+v 0.588893 -2.961370 0.346768
+v 0.355431 -2.867654 0.342733
+v 0.121970 -2.773938 0.338698
+v -0.111491 -2.680223 0.334663
+v -0.344953 -2.586506 0.330628
+v -0.578414 -2.492791 0.326593
+v -0.811875 -2.399075 0.322558
+v -1.045337 -2.305359 0.318523
+v -1.278798 -2.211644 0.314488
+v -1.512259 -2.117928 0.310453
+v -1.745721 -2.024212 0.306418
+v -1.979182 -1.930496 0.302383
+v -2.212643 -1.836780 0.298348
+v -2.446105 -1.743064 0.294313
+v -2.679566 -1.649349 0.290278
+v -2.913028 -1.555633 0.286243
+v -3.146489 -1.461917 0.282208
+v -3.379950 -1.368201 0.278173
+v -3.613411 -1.274486 0.274138
+v -3.846873 -1.180770 0.270103
+v -4.080334 -1.087054 0.266068
+v -4.313795 -0.993338 0.262033
+v 2.853667 -3.735186 0.377481
+v 2.620206 -3.641469 0.373446
+v 2.386744 -3.547754 0.369411
+v 2.153283 -3.454038 0.365376
+v 1.919822 -3.360322 0.361341
+v 1.686360 -3.266606 0.357306
+v 1.452899 -3.172890 0.353271
+v 1.219437 -3.079174 0.349236
+v 0.985976 -2.985458 0.345201
+v 0.752515 -2.891742 0.341166
+v 0.519053 -2.798027 0.337131
+v 0.285592 -2.704310 0.333096
+v 0.052131 -2.610595 0.329061
+v -0.181331 -2.516879 0.325026
+v -0.414792 -2.423163 0.320991
+v -0.648253 -2.329447 0.316956
+v -0.881715 -2.235731 0.312921
+v -1.115176 -2.142015 0.308886
+v -1.348638 -2.048300 0.304851
+v -1.582099 -1.954584 0.300816
+v -1.815560 -1.860868 0.296781
+v -2.049021 -1.767152 0.292746
+v -2.282483 -1.673437 0.288711
+v -2.515944 -1.579721 0.284676
+v -2.749406 -1.486005 0.280641
+v -2.982867 -1.392290 0.276606
+v -3.216328 -1.298574 0.272572
+v -3.449790 -1.204858 0.268537
+v -3.683251 -1.111142 0.264502
+v -3.916712 -1.017426 0.260467
+v -4.150173 -0.923711 0.256432
+v -4.383635 -0.829995 0.252397
+v 3.017289 -3.665558 0.371879
+v 2.783828 -3.571841 0.367844
+v 2.550366 -3.478126 0.363809
+v 2.316905 -3.384410 0.359774
+v 2.083444 -3.290694 0.355739
+v 1.849982 -3.196978 0.351704
+v 1.616521 -3.103262 0.347669
+v 1.383060 -3.009546 0.343634
+v 1.149598 -2.915830 0.339599
+v 0.916137 -2.822114 0.335564
+v 0.682675 -2.728399 0.331529
+v 0.449214 -2.634683 0.327494
+v 0.215753 -2.540967 0.323459
+v -0.017709 -2.447251 0.319424
+v -0.251170 -2.353535 0.315389
+v -0.484631 -2.259820 0.311354
+v -0.718093 -2.166104 0.307319
+v -0.951554 -2.072388 0.303284
+v -1.185016 -1.978672 0.299249
+v -1.418477 -1.884956 0.295214
+v -1.651938 -1.791241 0.291179
+v -1.885400 -1.697525 0.287144
+v -2.118861 -1.603809 0.283109
+v -2.352322 -1.510093 0.279074
+v -2.585784 -1.416377 0.275039
+v -2.819245 -1.322662 0.271004
+v -3.052706 -1.228946 0.266969
+v -3.286168 -1.135230 0.262934
+v -3.519629 -1.041514 0.258899
+v -3.753090 -0.947798 0.254864
+v -3.986552 -0.854083 0.250829
+v -4.220013 -0.760367 0.246794
+v -4.453474 -0.666651 0.242759
+v 3.180911 -3.595930 0.366277
+v 2.947450 -3.502214 0.362242
+v 2.713988 -3.408498 0.358207
+v 2.480527 -3.314782 0.354172
+v 2.247066 -3.221066 0.350137
+v 2.013604 -3.127350 0.346102
+v 1.780143 -3.033635 0.342067
+v 1.546681 -2.939919 0.338032
+v 1.313220 -2.846202 0.333997
+v 1.079759 -2.752487 0.329962
+v 0.846297 -2.658771 0.325927
+v 0.612836 -2.565055 0.321892
+v 0.379375 -2.471339 0.317857
+v 0.145913 -2.377623 0.313822
+v -0.087548 -2.283908 0.309787
+v -0.321009 -2.190192 0.305752
+v -0.554471 -2.096476 0.301717
+v -0.787932 -2.002760 0.297682
+v -1.021394 -1.909044 0.293647
+v -1.254855 -1.815328 0.289612
+v -1.488316 -1.721613 0.285577
+v -1.721778 -1.627897 0.281542
+v -1.955239 -1.534181 0.277507
+v -2.188700 -1.440465 0.273472
+v -2.422162 -1.346750 0.269437
+v -2.655623 -1.253034 0.265402
+v -2.889084 -1.159318 0.261367
+v -3.122546 -1.065602 0.257332
+v -3.356007 -0.971886 0.253297
+v -3.589468 -0.878170 0.249262
+v -3.822929 -0.784455 0.245227
+v -4.056391 -0.690739 0.241192
+v -4.289852 -0.597024 0.237157
+v -4.523314 -0.503308 0.233122
+v 3.344533 -3.526303 0.360675
+v 3.111072 -3.432586 0.356640
+v 2.877610 -3.338870 0.352605
+v 2.644149 -3.245154 0.348570
+v 2.410687 -3.151438 0.344535
+v 2.177226 -3.057723 0.340500
+v 1.943765 -2.964007 0.336465
+v 1.710303 -2.870291 0.332430
+v 1.476842 -2.776575 0.328395
+v 1.243381 -2.682859 0.324360
+v 1.009919 -2.589143 0.320325
+v 0.776458 -2.495427 0.316290
+v 0.542997 -2.401711 0.312255
+v 0.309535 -2.307995 0.308220
+v 0.076074 -2.214280 0.304185
+v -0.157387 -2.120564 0.300150
+v -0.390849 -2.026848 0.296115
+v -0.624310 -1.933132 0.292080
+v -0.857772 -1.839417 0.288045
+v -1.091233 -1.745700 0.284010
+v -1.324694 -1.651985 0.279975
+v -1.558156 -1.558269 0.275940
+v -1.791617 -1.464553 0.271905
+v -2.025078 -1.370837 0.267870
+v -2.258540 -1.277122 0.263835
+v -2.492001 -1.183406 0.259800
+v -2.725462 -1.089690 0.255765
+v -2.958924 -0.995974 0.251730
+v -3.192385 -0.902259 0.247695
+v -3.425846 -0.808543 0.243660
+v -3.659307 -0.714827 0.239625
+v -3.892769 -0.621111 0.235590
+v -4.126230 -0.527396 0.231555
+v -4.359692 -0.433680 0.227520
+v -4.593153 -0.339964 0.223485
+v 3.508155 -3.456674 0.355073
+v 3.274693 -3.362958 0.351038
+v 3.041232 -3.269243 0.347003
+v 2.807771 -3.175527 0.342968
+v 2.574309 -3.081810 0.338933
+v 2.340848 -2.988095 0.334898
+v 2.107387 -2.894379 0.330863
+v 1.873925 -2.800663 0.326828
+v 1.640464 -2.706947 0.322793
+v 1.407002 -2.613231 0.318758
+v 1.173541 -2.519516 0.314723
+v 0.940080 -2.425799 0.310688
+v 0.706618 -2.332083 0.306653
+v 0.473157 -2.238368 0.302618
+v 0.239696 -2.144652 0.298583
+v 0.006234 -2.050936 0.294548
+v -0.227227 -1.957220 0.290513
+v -0.460688 -1.863505 0.286478
+v -0.694150 -1.769789 0.282443
+v -0.927611 -1.676073 0.278408
+v -1.161072 -1.582357 0.274373
+v -1.394534 -1.488641 0.270338
+v -1.627995 -1.394925 0.266303
+v -1.861456 -1.301210 0.262268
+v -2.094918 -1.207494 0.258233
+v -2.328379 -1.113778 0.254198
+v -2.561840 -1.020062 0.250163
+v -2.795302 -0.926347 0.246128
+v -3.028763 -0.832631 0.242093
+v -3.262224 -0.738915 0.238058
+v -3.495686 -0.645199 0.234023
+v -3.729147 -0.551483 0.229988
+v -3.962608 -0.457768 0.225953
+v -4.196070 -0.364052 0.221918
+v -4.429531 -0.270336 0.217883
+v -4.662992 -0.176620 0.213848
+v 3.671777 -3.387047 0.349471
+v 3.438316 -3.293330 0.345436
+v 3.204854 -3.199615 0.341401
+v 2.971393 -3.105899 0.337366
+v 2.737931 -3.012183 0.333331
+v 2.504470 -2.918467 0.329296
+v 2.271009 -2.824751 0.325261
+v 2.037547 -2.731035 0.321226
+v 1.804086 -2.637319 0.317191
+v 1.570624 -2.543603 0.313156
+v 1.337163 -2.449888 0.309121
+v 1.103702 -2.356172 0.305086
+v 0.870240 -2.262455 0.301051
+v 0.636779 -2.168740 0.297016
+v 0.403318 -2.075024 0.292981
+v 0.169856 -1.981308 0.288946
+v -0.063605 -1.887592 0.284911
+v -0.297066 -1.793877 0.280876
+v -0.530528 -1.700161 0.276841
+v -0.763989 -1.606445 0.272806
+v -0.997450 -1.512729 0.268771
+v -1.230912 -1.419013 0.264736
+v -1.464373 -1.325298 0.260701
+v -1.697834 -1.231582 0.256666
+v -1.931295 -1.137866 0.252631
+v -2.164757 -1.044150 0.248596
+v -2.398218 -0.950434 0.244561
+v -2.631680 -0.856719 0.240526
+v -2.865141 -0.763003 0.236491
+v -3.098603 -0.669287 0.232456
+v -3.332064 -0.575571 0.228421
+v -3.565525 -0.481856 0.224386
+v -3.798986 -0.388140 0.220351
+v -4.032447 -0.294424 0.216316
+v -4.265909 -0.200708 0.212281
+v -4.499370 -0.106993 0.208246
+v -4.732831 -0.013277 0.204211
+v 3.835399 -3.317418 0.343869
+v 3.601938 -3.223703 0.339834
+v 3.368476 -3.129987 0.335799
+v 3.135015 -3.036271 0.331764
+v 2.901554 -2.942555 0.327729
+v 2.668092 -2.848839 0.323694
+v 2.434631 -2.755123 0.319659
+v 2.201169 -2.661407 0.315624
+v 1.967708 -2.567691 0.311589
+v 1.734246 -2.473976 0.307554
+v 1.500785 -2.380260 0.303519
+v 1.267324 -2.286544 0.299484
+v 1.033862 -2.192828 0.295449
+v 0.800401 -2.099112 0.291414
+v 0.566940 -2.005396 0.287379
+v 0.333478 -1.911680 0.283344
+v 0.100017 -1.817965 0.279309
+v -0.133444 -1.724249 0.275274
+v -0.366906 -1.630533 0.271239
+v -0.600367 -1.536817 0.267204
+v -0.833828 -1.443102 0.263169
+v -1.067290 -1.349386 0.259134
+v -1.300751 -1.255670 0.255099
+v -1.534212 -1.161954 0.251064
+v -1.767674 -1.068238 0.247029
+v -2.001135 -0.974522 0.242994
+v -2.234596 -0.880807 0.238959
+v -2.468058 -0.787091 0.234924
+v -2.701519 -0.693375 0.230889
+v -2.934980 -0.599659 0.226854
+v -3.168442 -0.505944 0.222819
+v -3.401903 -0.412228 0.218784
+v -3.635364 -0.318512 0.214749
+v -3.868825 -0.224796 0.210714
+v -4.102286 -0.131081 0.206679
+v -4.335748 -0.037365 0.202644
+v -4.569209 0.056351 0.198609
+v -4.802670 0.150067 0.194574
+v 3.999021 -3.247791 0.338267
+v 3.765560 -3.154075 0.334232
+v 3.532098 -3.060359 0.330197
+v 3.298637 -2.966643 0.326162
+v 3.065176 -2.872927 0.322127
+v 2.831714 -2.779212 0.318092
+v 2.598253 -2.685495 0.314057
+v 2.364791 -2.591780 0.310022
+v 2.131330 -2.498064 0.305987
+v 1.897868 -2.404348 0.301952
+v 1.664407 -2.310632 0.297917
+v 1.430946 -2.216916 0.293882
+v 1.197484 -2.123200 0.289847
+v 0.964023 -2.029484 0.285812
+v 0.730562 -1.935768 0.281777
+v 0.497100 -1.842052 0.277742
+v 0.263639 -1.748337 0.273707
+v 0.030178 -1.654621 0.269672
+v -0.203284 -1.560905 0.265637
+v -0.436745 -1.467189 0.261602
+v -0.670206 -1.373474 0.257567
+v -0.903668 -1.279758 0.253532
+v -1.137129 -1.186042 0.249497
+v -1.370590 -1.092326 0.245462
+v -1.604052 -0.998610 0.241427
+v -1.837513 -0.904895 0.237392
+v -2.070974 -0.811179 0.233357
+v -2.304435 -0.717463 0.229322
+v -2.537897 -0.623747 0.225287
+v -2.771358 -0.530031 0.221252
+v -3.004820 -0.436316 0.217217
+v -3.238281 -0.342600 0.213182
+v -3.471742 -0.248884 0.209147
+v -3.705204 -0.155168 0.205112
+v -3.938665 -0.061453 0.201077
+v -4.172126 0.032263 0.197042
+v -4.405587 0.125979 0.193007
+v -4.639049 0.219695 0.188972
+v -4.872510 0.313411 0.184937
+v 4.162643 -3.178163 0.332665
+v 3.929182 -3.084447 0.328630
+v 3.695721 -2.990731 0.324595
+v 3.462259 -2.897015 0.320560
+v 3.228797 -2.803299 0.316525
+v 2.995336 -2.709584 0.312490
+v 2.761875 -2.615868 0.308455
+v 2.528413 -2.522151 0.304420
+v 2.294952 -2.428436 0.300385
+v 2.061491 -2.334720 0.296350
+v 1.828029 -2.241004 0.292315
+v 1.594568 -2.147288 0.288280
+v 1.361106 -2.053572 0.284245
+v 1.127645 -1.959856 0.280210
+v 0.894184 -1.866141 0.276175
+v 0.660722 -1.772425 0.272140
+v 0.427261 -1.678709 0.268105
+v 0.193800 -1.584993 0.264070
+v -0.039662 -1.491277 0.260035
+v -0.273123 -1.397561 0.256000
+v -0.506584 -1.303846 0.251965
+v -0.740046 -1.210130 0.247930
+v -0.973507 -1.116414 0.243895
+v -1.206968 -1.022698 0.239860
+v -1.440430 -0.928983 0.235825
+v -1.673891 -0.835267 0.231790
+v -1.907352 -0.741551 0.227755
+v -2.140813 -0.647835 0.223720
+v -2.374275 -0.554119 0.219685
+v -2.607736 -0.460404 0.215650
+v -2.841197 -0.366688 0.211615
+v -3.074659 -0.272972 0.207580
+v -3.308120 -0.179256 0.203545
+v -3.541582 -0.085541 0.199510
+v -3.775043 0.008175 0.195475
+v -4.008504 0.101891 0.191440
+v -4.241965 0.195607 0.187405
+v -4.475427 0.289323 0.183370
+v -4.708888 0.383039 0.179335
+v -4.942349 0.476755 0.175300
+v 4.326265 -3.108535 0.327063
+v 4.092804 -3.014819 0.323028
+v 3.859343 -2.921103 0.318993
+v 3.625881 -2.827387 0.314958
+v 3.392420 -2.733672 0.310923
+v 3.158958 -2.639956 0.306888
+v 2.925497 -2.546240 0.302853
+v 2.692035 -2.452524 0.298818
+v 2.458574 -2.358808 0.294783
+v 2.225112 -2.265092 0.290748
+v 1.991651 -2.171377 0.286713
+v 1.758190 -2.077660 0.282678
+v 1.524728 -1.983944 0.278643
+v 1.291267 -1.890228 0.274608
+v 1.057806 -1.796513 0.270573
+v 0.824344 -1.702797 0.266538
+v 0.590883 -1.609081 0.262503
+v 0.357422 -1.515365 0.258468
+v 0.123960 -1.421649 0.254433
+v -0.109501 -1.327934 0.250398
+v -0.342962 -1.234218 0.246363
+v -0.576424 -1.140502 0.242328
+v -0.809885 -1.046786 0.238293
+v -1.043346 -0.953071 0.234258
+v -1.276808 -0.859355 0.230223
+v -1.510269 -0.765639 0.226188
+v -1.743730 -0.671923 0.222153
+v -1.977192 -0.578207 0.218118
+v -2.210653 -0.484491 0.214083
+v -2.444114 -0.390776 0.210048
+v -2.677576 -0.297060 0.206013
+v -2.911037 -0.203344 0.201978
+v -3.144498 -0.109628 0.197943
+v -3.377960 -0.015913 0.193908
+v -3.611421 0.077803 0.189873
+v -3.844882 0.171519 0.185838
+v -4.078343 0.265235 0.181803
+v -4.311805 0.358951 0.177768
+v -4.545266 0.452667 0.173733
+v -4.778728 0.546382 0.169698
+v -5.012189 0.640098 0.165663
+v 4.489887 -3.038907 0.321461
+v 4.256426 -2.945192 0.317426
+v 4.022964 -2.851475 0.313390
+v 3.789503 -2.757760 0.309355
+v 3.556042 -2.664043 0.305321
+v 3.322580 -2.570328 0.301286
+v 3.089119 -2.476612 0.297251
+v 2.855658 -2.382896 0.293216
+v 2.622196 -2.289180 0.289181
+v 2.388735 -2.195465 0.285146
+v 2.155273 -2.101748 0.281111
+v 1.921812 -2.008032 0.277076
+v 1.688350 -1.914317 0.273041
+v 1.454889 -1.820600 0.269006
+v 1.221428 -1.726885 0.264971
+v 0.987966 -1.633169 0.260936
+v 0.754505 -1.539453 0.256901
+v 0.521044 -1.445737 0.252866
+v 0.287582 -1.352022 0.248831
+v 0.054121 -1.258306 0.244796
+v -0.179340 -1.164590 0.240761
+v -0.412802 -1.070874 0.236726
+v -0.646263 -0.977158 0.232691
+v -0.879724 -0.883443 0.228656
+v -1.113186 -0.789727 0.224621
+v -1.346647 -0.696011 0.220586
+v -1.580108 -0.602295 0.216551
+v -1.813570 -0.508579 0.212516
+v -2.047031 -0.414864 0.208481
+v -2.280492 -0.321148 0.204446
+v -2.513954 -0.227432 0.200411
+v -2.747415 -0.133716 0.196376
+v -2.980876 -0.040001 0.192341
+v -3.214338 0.053715 0.188306
+v -3.447799 0.147431 0.184271
+v -3.681260 0.241147 0.180236
+v -3.914722 0.334863 0.176201
+v -4.148183 0.428579 0.172166
+v -4.381644 0.522295 0.168131
+v -4.615106 0.616011 0.164096
+v -4.848567 0.709726 0.160061
+v -5.082028 0.803442 0.156026
+v 4.653510 -2.969280 0.315859
+v 4.420048 -2.875564 0.311824
+v 4.186587 -2.781847 0.307789
+v 3.953125 -2.688132 0.303754
+v 3.719664 -2.594416 0.299719
+v 3.486202 -2.500700 0.295684
+v 3.252741 -2.406984 0.291649
+v 3.019279 -2.313268 0.287614
+v 2.785818 -2.219553 0.283579
+v 2.552357 -2.125836 0.279544
+v 2.318895 -2.032120 0.275509
+v 2.085434 -1.938404 0.271474
+v 1.851972 -1.844689 0.267439
+v 1.618511 -1.750973 0.263404
+v 1.385050 -1.657257 0.259369
+v 1.151588 -1.563541 0.255334
+v 0.918127 -1.469826 0.251299
+v 0.684666 -1.376110 0.247264
+v 0.451204 -1.282394 0.243229
+v 0.217743 -1.188678 0.239194
+v -0.015718 -1.094962 0.235159
+v -0.249180 -1.001246 0.231124
+v -0.482641 -0.907531 0.227089
+v -0.716102 -0.813815 0.223054
+v -0.949564 -0.720099 0.219019
+v -1.183025 -0.626383 0.214984
+v -1.416486 -0.532667 0.210949
+v -1.649948 -0.438952 0.206914
+v -1.883409 -0.345236 0.202879
+v -2.116870 -0.251520 0.198844
+v -2.350331 -0.157804 0.194809
+v -2.583793 -0.064088 0.190774
+v -2.817254 0.029627 0.186739
+v -3.050715 0.123343 0.182704
+v -3.284177 0.217059 0.178669
+v -3.517638 0.310775 0.174634
+v -3.751100 0.404491 0.170599
+v -3.984561 0.498207 0.166564
+v -4.218022 0.591923 0.162529
+v -4.451484 0.685638 0.158494
+v -4.684945 0.779354 0.154459
+v -4.918406 0.873070 0.150424
+v -5.151868 0.966786 0.146389
+v 4.817132 -2.899652 0.310257
+v 4.583670 -2.805936 0.306221
+v 4.350208 -2.712219 0.302186
+v 4.116747 -2.618504 0.298151
+v 3.883286 -2.524788 0.294116
+v 3.649824 -2.431072 0.290082
+v 3.416363 -2.337356 0.286047
+v 3.182901 -2.243640 0.282012
+v 2.949440 -2.149925 0.277977
+v 2.715979 -2.056208 0.273942
+v 2.482517 -1.962493 0.269907
+v 2.249056 -1.868777 0.265872
+v 2.015594 -1.775061 0.261837
+v 1.782133 -1.681345 0.257802
+v 1.548671 -1.587629 0.253767
+v 1.315210 -1.493914 0.249732
+v 1.081749 -1.400198 0.245697
+v 0.848288 -1.306482 0.241662
+v 0.614826 -1.212766 0.237627
+v 0.381365 -1.119050 0.233592
+v 0.147904 -1.025334 0.229557
+v -0.085558 -0.931619 0.225522
+v -0.319019 -0.837903 0.221487
+v -0.552480 -0.744187 0.217452
+v -0.785942 -0.650471 0.213417
+v -1.019403 -0.556755 0.209382
+v -1.252864 -0.463039 0.205347
+v -1.486326 -0.369324 0.201312
+v -1.719787 -0.275608 0.197277
+v -1.953248 -0.181892 0.193242
+v -2.186710 -0.088176 0.189207
+v -2.420171 0.005539 0.185172
+v -2.653632 0.099255 0.181137
+v -2.887094 0.192971 0.177102
+v -3.120555 0.286687 0.173067
+v -3.354016 0.380403 0.169032
+v -3.587478 0.474118 0.164997
+v -3.820939 0.567834 0.160962
+v -4.054400 0.661550 0.156927
+v -4.287862 0.755266 0.152892
+v -4.521323 0.848982 0.148857
+v -4.754785 0.942698 0.144822
+v -4.988246 1.036414 0.140787
+v -5.221706 1.130129 0.136752
+v 4.980753 -2.830024 0.304654
+v 4.747292 -2.736308 0.300619
+v 4.513830 -2.642592 0.296584
+v 4.280369 -2.548876 0.292549
+v 4.046907 -2.455160 0.288514
+v 3.813446 -2.361444 0.284479
+v 3.579985 -2.267728 0.280444
+v 3.346523 -2.174013 0.276409
+v 3.113062 -2.080297 0.272375
+v 2.879601 -1.986581 0.268340
+v 2.646139 -1.892865 0.264305
+v 2.412678 -1.799149 0.260270
+v 2.179216 -1.705433 0.256235
+v 1.945755 -1.611717 0.252200
+v 1.712294 -1.518002 0.248165
+v 1.478832 -1.424286 0.244130
+v 1.245371 -1.330570 0.240095
+v 1.011909 -1.236854 0.236060
+v 0.778448 -1.143138 0.232025
+v 0.544987 -1.049423 0.227990
+v 0.311526 -0.955707 0.223955
+v 0.078064 -0.861991 0.219920
+v -0.155397 -0.768275 0.215885
+v -0.388859 -0.674559 0.211850
+v -0.622320 -0.580843 0.207815
+v -0.855781 -0.487128 0.203780
+v -1.089242 -0.393412 0.199745
+v -1.322704 -0.299696 0.195710
+v -1.556165 -0.205980 0.191675
+v -1.789626 -0.112264 0.187640
+v -2.023088 -0.018548 0.183605
+v -2.256549 0.075167 0.179570
+v -2.490010 0.168883 0.175535
+v -2.723472 0.262599 0.171500
+v -2.956933 0.356315 0.167465
+v -3.190394 0.450030 0.163430
+v -3.423856 0.543746 0.159395
+v -3.657317 0.637462 0.155360
+v -3.890779 0.731178 0.151325
+v -4.124240 0.824894 0.147290
+v -4.357701 0.918610 0.143255
+v -4.591162 1.012325 0.139220
+v -4.824624 1.106042 0.135185
+v -5.058085 1.199757 0.131150
+v -5.291546 1.293473 0.127115
+v 5.144376 -2.760396 0.299052
+v 4.910913 -2.666680 0.295017
+v 4.677453 -2.572964 0.290982
+v 4.443991 -2.479249 0.286947
+v 4.210530 -2.385532 0.282912
+v 3.977068 -2.291817 0.278877
+v 3.743607 -2.198101 0.274843
+v 3.510145 -2.104385 0.270808
+v 3.276684 -2.010669 0.266773
+v 3.043222 -1.916953 0.262738
+v 2.809761 -1.823237 0.258703
+v 2.576299 -1.729521 0.254668
+v 2.342838 -1.635805 0.250633
+v 2.109377 -1.542089 0.246598
+v 1.875915 -1.448374 0.242563
+v 1.642454 -1.354658 0.238528
+v 1.408993 -1.260942 0.234493
+v 1.175532 -1.167226 0.230458
+v 0.942070 -1.073511 0.226423
+v 0.708609 -0.979795 0.222388
+v 0.475148 -0.886079 0.218353
+v 0.241686 -0.792363 0.214318
+v 0.008225 -0.698647 0.210283
+v -0.225236 -0.604931 0.206248
+v -0.458698 -0.511216 0.202213
+v -0.692159 -0.417500 0.198178
+v -0.925620 -0.323784 0.194143
+v -1.159082 -0.230068 0.190108
+v -1.392543 -0.136352 0.186073
+v -1.626004 -0.042636 0.182038
+v -1.859466 0.051079 0.178003
+v -2.092927 0.144795 0.173968
+v -2.326388 0.238511 0.169933
+v -2.559850 0.332227 0.165898
+v -2.793311 0.425943 0.161863
+v -3.026772 0.519658 0.157828
+v -3.260234 0.613374 0.153793
+v -3.493695 0.707090 0.149758
+v -3.727157 0.800806 0.145723
+v -3.960618 0.894522 0.141688
+v -4.194079 0.988238 0.137653
+v -4.427540 1.081954 0.133618
+v -4.661001 1.175669 0.129583
+v -4.894464 1.269385 0.125548
+v -5.127924 1.363101 0.121513
+v -5.361385 1.456817 0.117478
+v 5.307998 -2.690768 0.293450
+v 5.074536 -2.597052 0.289415
+v 4.841075 -2.503336 0.285380
+v 4.607614 -2.409621 0.281345
+v 4.374152 -2.315905 0.277310
+v 4.140691 -2.222188 0.273275
+v 3.907229 -2.128473 0.269240
+v 3.673767 -2.034757 0.265205
+v 3.440306 -1.941041 0.261170
+v 3.206845 -1.847325 0.257135
+v 2.973383 -1.753609 0.253100
+v 2.739922 -1.659893 0.249065
+v 2.506460 -1.566177 0.245030
+v 2.272999 -1.472462 0.240995
+v 2.039538 -1.378746 0.236960
+v 1.806076 -1.285030 0.232925
+v 1.572615 -1.191314 0.228890
+v 1.339153 -1.097599 0.224855
+v 1.105692 -1.003883 0.220821
+v 0.872231 -0.910167 0.216786
+v 0.638770 -0.816451 0.212751
+v 0.405308 -0.722735 0.208716
+v 0.171847 -0.629019 0.204681
+v -0.061614 -0.535303 0.200646
+v -0.295076 -0.441588 0.196611
+v -0.528537 -0.347872 0.192576
+v -0.761998 -0.254156 0.188541
+v -0.995460 -0.160440 0.184506
+v -1.228921 -0.066724 0.180471
+v -1.462382 0.026991 0.176436
+v -1.695844 0.120707 0.172401
+v -1.929305 0.214423 0.168366
+v -2.162766 0.308139 0.164331
+v -2.396228 0.401855 0.160296
+v -2.629689 0.495571 0.156261
+v -2.863150 0.589286 0.152226
+v -3.096612 0.683002 0.148191
+v -3.330073 0.776718 0.144156
+v -3.563535 0.870434 0.140121
+v -3.796996 0.964150 0.136086
+v -4.030457 1.057866 0.132051
+v -4.263918 1.151582 0.128016
+v -4.497379 1.245297 0.123981
+v -4.730841 1.339013 0.119946
+v -4.964303 1.432729 0.115911
+v -5.197763 1.526445 0.111876
+v -5.431225 1.620160 0.107841
+v 5.471620 -2.621141 0.287848
+v 5.238158 -2.527424 0.283813
+v 5.004697 -2.433708 0.279778
+v 4.771235 -2.339993 0.275743
+v 4.537774 -2.246277 0.271708
+v 4.304313 -2.152560 0.267673
+v 4.070851 -2.058845 0.263638
+v 3.837389 -1.965129 0.259603
+v 3.603928 -1.871413 0.255568
+v 3.370467 -1.777697 0.251533
+v 3.137005 -1.683981 0.247498
+v 2.903544 -1.590265 0.243463
+v 2.670082 -1.496549 0.239429
+v 2.436621 -1.402834 0.235394
+v 2.203160 -1.309118 0.231359
+v 1.969698 -1.215402 0.227324
+v 1.736237 -1.121686 0.223289
+v 1.502776 -1.027971 0.219254
+v 1.269314 -0.934255 0.215219
+v 1.035853 -0.840539 0.211184
+v 0.802391 -0.746823 0.207149
+v 0.568930 -0.653107 0.203114
+v 0.335469 -0.559391 0.199079
+v 0.102008 -0.465676 0.195044
+v -0.131454 -0.371960 0.191009
+v -0.364915 -0.278244 0.186974
+v -0.598377 -0.184528 0.182939
+v -0.831838 -0.090812 0.178904
+v -1.065299 0.002903 0.174869
+v -1.298761 0.096619 0.170834
+v -1.532222 0.190335 0.166799
+v -1.765683 0.284051 0.162764
+v -1.999144 0.377767 0.158729
+v -2.232605 0.471483 0.154694
+v -2.466067 0.565198 0.150659
+v -2.699528 0.658914 0.146624
+v -2.932990 0.752630 0.142589
+v -3.166451 0.846346 0.138554
+v -3.399912 0.940062 0.134519
+v -3.633374 1.033778 0.130484
+v -3.866836 1.127494 0.126449
+v -4.100297 1.221209 0.122414
+v -4.333757 1.314925 0.118379
+v -4.567219 1.408641 0.114344
+v -4.800680 1.502357 0.110309
+v -5.034142 1.596073 0.106274
+v -5.267603 1.689788 0.102239
+v -5.501064 1.783504 0.098204
+v 5.635241 -2.551513 0.282246
+v 5.401779 -2.457797 0.278211
+v 5.168319 -2.364081 0.274176
+v 4.934856 -2.270365 0.270141
+v 4.701396 -2.176649 0.266106
+v 4.467934 -2.082933 0.262071
+v 4.234472 -1.989217 0.258036
+v 4.001011 -1.895501 0.254001
+v 3.767550 -1.801785 0.249966
+v 3.534088 -1.708070 0.245931
+v 3.300627 -1.614354 0.241896
+v 3.067165 -1.520638 0.237861
+v 2.833704 -1.426922 0.233826
+v 2.600243 -1.333206 0.229791
+v 2.366781 -1.239491 0.225756
+v 2.133320 -1.145774 0.221721
+v 1.899859 -1.052059 0.217686
+v 1.666397 -0.958343 0.213651
+v 1.432936 -0.864627 0.209616
+v 1.199475 -0.770911 0.205581
+v 0.966013 -0.677196 0.201546
+v 0.732552 -0.583480 0.197511
+v 0.499091 -0.489764 0.193476
+v 0.265629 -0.396048 0.189441
+v 0.032168 -0.302332 0.185406
+v -0.201293 -0.208616 0.181371
+v -0.434755 -0.114901 0.177336
+v -0.668216 -0.021185 0.173302
+v -0.901677 0.072531 0.169267
+v -1.135139 0.166247 0.165232
+v -1.368600 0.259963 0.161197
+v -1.602061 0.353679 0.157162
+v -1.835523 0.447395 0.153127
+v -2.068984 0.541110 0.149092
+v -2.302445 0.634826 0.145057
+v -2.535906 0.728542 0.141022
+v -2.769368 0.822258 0.136987
+v -3.002829 0.915974 0.132952
+v -3.236290 1.009689 0.128917
+v -3.469752 1.103406 0.124882
+v -3.703213 1.197121 0.120847
+v -3.936675 1.290837 0.116812
+v -4.170135 1.384553 0.112777
+v -4.403597 1.478269 0.108742
+v -4.637058 1.571984 0.104707
+v -4.870520 1.665701 0.100672
+v -5.103981 1.759416 0.096637
+v -5.337442 1.853132 0.092602
+v -5.570904 1.946848 0.088567
+vn 0.0077 0.0622 0.9980
+usemtl None
+s off
+f 2//1 254//1 104//1
+f 2//1 105//1 254//1
+f 205//1 204//1 3//1
+f 206//1 255//1 205//1
+f 207//1 256//1 206//1
+f 208//1 258//1 207//1
+f 209//1 261//1 208//1
+f 210//1 265//1 209//1
+f 211//1 270//1 210//1
+f 212//1 276//1 211//1
+f 213//1 283//1 212//1
+f 214//1 291//1 213//1
+f 215//1 300//1 214//1
+f 216//1 310//1 215//1
+f 217//1 321//1 216//1
+f 218//1 333//1 217//1
+f 219//1 346//1 218//1
+f 220//1 360//1 219//1
+f 221//1 375//1 220//1
+f 222//1 391//1 221//1
+f 223//1 408//1 222//1
+f 224//1 426//1 223//1
+f 225//1 445//1 224//1
+f 226//1 465//1 225//1
+f 227//1 486//1 226//1
+f 228//1 508//1 227//1
+f 229//1 531//1 228//1
+f 230//1 555//1 229//1
+f 231//1 580//1 230//1
+f 232//1 606//1 231//1
+f 233//1 633//1 232//1
+f 234//1 661//1 233//1
+f 235//1 690//1 234//1
+f 236//1 720//1 235//1
+f 237//1 751//1 236//1
+f 238//1 783//1 237//1
+f 239//1 816//1 238//1
+f 240//1 850//1 239//1
+f 241//1 885//1 240//1
+f 242//1 921//1 241//1
+f 243//1 958//1 242//1
+f 244//1 996//1 243//1
+f 245//1 1035//1 244//1
+f 246//1 1075//1 245//1
+f 247//1 1116//1 246//1
+f 248//1 1158//1 247//1
+f 249//1 1201//1 248//1
+f 250//1 1245//1 249//1
+f 251//1 1290//1 250//1
+f 252//1 1336//1 251//1
+f 253//1 1383//1 252//1
+f 254//1 1431//1 253//1
+f 205//1 255//1 204//1
+f 255//1 203//1 204//1
+f 206//1 256//1 255//1
+f 256//1 257//1 255//1
+f 255//1 257//1 203//1
+f 257//1 202//1 203//1
+f 207//1 258//1 256//1
+f 258//1 259//1 256//1
+f 256//1 259//1 257//1
+f 259//1 260//1 257//1
+f 257//1 260//1 202//1
+f 260//1 201//1 202//1
+f 208//1 261//1 258//1
+f 261//1 262//1 258//1
+f 258//1 262//1 259//1
+f 262//1 263//1 259//1
+f 259//1 263//1 260//1
+f 263//1 264//1 260//1
+f 260//1 264//1 201//1
+f 264//1 200//1 201//1
+f 209//1 265//1 261//1
+f 265//1 266//1 261//1
+f 261//1 266//1 262//1
+f 266//1 267//1 262//1
+f 262//1 267//1 263//1
+f 267//1 268//1 263//1
+f 263//1 268//1 264//1
+f 268//1 269//1 264//1
+f 264//1 269//1 200//1
+f 269//1 199//1 200//1
+f 210//1 270//1 265//1
+f 270//1 271//1 265//1
+f 265//1 271//1 266//1
+f 271//1 272//1 266//1
+f 266//1 272//1 267//1
+f 272//1 273//1 267//1
+f 267//1 273//1 268//1
+f 273//1 274//1 268//1
+f 268//1 274//1 269//1
+f 274//1 275//1 269//1
+f 269//1 275//1 199//1
+f 275//1 198//1 199//1
+f 211//1 276//1 270//1
+f 276//1 277//1 270//1
+f 270//1 277//1 271//1
+f 277//1 278//1 271//1
+f 271//1 278//1 272//1
+f 278//1 279//1 272//1
+f 272//1 279//1 273//1
+f 279//1 280//1 273//1
+f 273//1 280//1 274//1
+f 280//1 281//1 274//1
+f 274//1 281//1 275//1
+f 281//1 282//1 275//1
+f 275//1 282//1 198//1
+f 282//1 197//1 198//1
+f 212//1 283//1 276//1
+f 283//1 284//1 276//1
+f 276//1 284//1 277//1
+f 284//1 285//1 277//1
+f 277//1 285//1 278//1
+f 285//1 286//1 278//1
+f 278//1 286//1 279//1
+f 286//1 287//1 279//1
+f 279//1 287//1 280//1
+f 287//1 288//1 280//1
+f 280//1 288//1 281//1
+f 288//1 289//1 281//1
+f 281//1 289//1 282//1
+f 289//1 290//1 282//1
+f 282//1 290//1 197//1
+f 290//1 196//1 197//1
+f 213//1 291//1 283//1
+f 291//1 292//1 283//1
+f 283//1 292//1 284//1
+f 292//1 293//1 284//1
+f 284//1 293//1 285//1
+f 293//1 294//1 285//1
+f 285//1 294//1 286//1
+f 294//1 295//1 286//1
+f 286//1 295//1 287//1
+f 295//1 296//1 287//1
+f 287//1 296//1 288//1
+f 296//1 297//1 288//1
+f 288//1 297//1 289//1
+f 297//1 298//1 289//1
+f 289//1 298//1 290//1
+f 298//1 299//1 290//1
+f 290//1 299//1 196//1
+f 299//1 195//1 196//1
+f 214//1 300//1 291//1
+f 300//1 301//1 291//1
+f 291//1 301//1 292//1
+f 301//1 302//1 292//1
+f 292//1 302//1 293//1
+f 302//1 303//1 293//1
+f 293//1 303//1 294//1
+f 303//1 304//1 294//1
+f 294//1 304//1 295//1
+f 304//1 305//1 295//1
+f 295//1 305//1 296//1
+f 305//1 306//1 296//1
+f 296//1 306//1 297//1
+f 306//1 307//1 297//1
+f 297//1 307//1 298//1
+f 307//1 308//1 298//1
+f 298//1 308//1 299//1
+f 308//1 309//1 299//1
+f 299//1 309//1 195//1
+f 309//1 194//1 195//1
+f 215//1 310//1 300//1
+f 310//1 311//1 300//1
+f 300//1 311//1 301//1
+f 311//1 312//1 301//1
+f 301//1 312//1 302//1
+f 312//1 313//1 302//1
+f 302//1 313//1 303//1
+f 313//1 314//1 303//1
+f 303//1 314//1 304//1
+f 314//1 315//1 304//1
+f 304//1 315//1 305//1
+f 315//1 316//1 305//1
+f 305//1 316//1 306//1
+f 316//1 317//1 306//1
+f 306//1 317//1 307//1
+f 317//1 318//1 307//1
+f 307//1 318//1 308//1
+f 318//1 319//1 308//1
+f 308//1 319//1 309//1
+f 319//1 320//1 309//1
+f 309//1 320//1 194//1
+f 320//1 193//1 194//1
+f 216//1 321//1 310//1
+f 321//1 322//1 310//1
+f 310//1 322//1 311//1
+f 322//1 323//1 311//1
+f 311//1 323//1 312//1
+f 323//1 324//1 312//1
+f 312//1 324//1 313//1
+f 324//1 325//1 313//1
+f 313//1 325//1 314//1
+f 325//1 326//1 314//1
+f 314//1 326//1 315//1
+f 326//1 327//1 315//1
+f 315//1 327//1 316//1
+f 327//1 328//1 316//1
+f 316//1 328//1 317//1
+f 328//1 329//1 317//1
+f 317//1 329//1 318//1
+f 329//1 330//1 318//1
+f 318//1 330//1 319//1
+f 330//1 331//1 319//1
+f 319//1 331//1 320//1
+f 331//1 332//1 320//1
+f 320//1 332//1 193//1
+f 332//1 192//1 193//1
+f 217//1 333//1 321//1
+f 333//1 334//1 321//1
+f 321//1 334//1 322//1
+f 334//1 335//1 322//1
+f 322//1 335//1 323//1
+f 335//1 336//1 323//1
+f 323//1 336//1 324//1
+f 336//1 337//1 324//1
+f 324//1 337//1 325//1
+f 337//1 338//1 325//1
+f 325//1 338//1 326//1
+f 338//1 339//1 326//1
+f 326//1 339//1 327//1
+f 339//1 340//1 327//1
+f 327//1 340//1 328//1
+f 340//1 341//1 328//1
+f 328//1 341//1 329//1
+f 341//1 342//1 329//1
+f 329//1 342//1 330//1
+f 342//1 343//1 330//1
+f 330//1 343//1 331//1
+f 343//1 344//1 331//1
+f 331//1 344//1 332//1
+f 344//1 345//1 332//1
+f 332//1 345//1 192//1
+f 345//1 191//1 192//1
+f 218//1 346//1 333//1
+f 346//1 347//1 333//1
+f 333//1 347//1 334//1
+f 347//1 348//1 334//1
+f 334//1 348//1 335//1
+f 348//1 349//1 335//1
+f 335//1 349//1 336//1
+f 349//1 350//1 336//1
+f 336//1 350//1 337//1
+f 350//1 351//1 337//1
+f 337//1 351//1 338//1
+f 351//1 352//1 338//1
+f 338//1 352//1 339//1
+f 352//1 353//1 339//1
+f 339//1 353//1 340//1
+f 353//1 354//1 340//1
+f 340//1 354//1 341//1
+f 354//1 355//1 341//1
+f 341//1 355//1 342//1
+f 355//1 356//1 342//1
+f 342//1 356//1 343//1
+f 356//1 357//1 343//1
+f 343//1 357//1 344//1
+f 357//1 358//1 344//1
+f 344//1 358//1 345//1
+f 358//1 359//1 345//1
+f 345//1 359//1 191//1
+f 359//1 190//1 191//1
+f 219//1 360//1 346//1
+f 360//1 361//1 346//1
+f 346//1 361//1 347//1
+f 361//1 362//1 347//1
+f 347//1 362//1 348//1
+f 362//1 363//1 348//1
+f 348//1 363//1 349//1
+f 363//1 364//1 349//1
+f 349//1 364//1 350//1
+f 364//1 365//1 350//1
+f 350//1 365//1 351//1
+f 365//1 366//1 351//1
+f 351//1 366//1 352//1
+f 366//1 367//1 352//1
+f 352//1 367//1 353//1
+f 367//1 368//1 353//1
+f 353//1 368//1 354//1
+f 368//1 369//1 354//1
+f 354//1 369//1 355//1
+f 369//1 370//1 355//1
+f 355//1 370//1 356//1
+f 370//1 371//1 356//1
+f 356//1 371//1 357//1
+f 371//1 372//1 357//1
+f 357//1 372//1 358//1
+f 372//1 373//1 358//1
+f 358//1 373//1 359//1
+f 373//1 374//1 359//1
+f 359//1 374//1 190//1
+f 374//1 189//1 190//1
+f 220//1 375//1 360//1
+f 375//1 376//1 360//1
+f 360//1 376//1 361//1
+f 376//1 377//1 361//1
+f 361//1 377//1 362//1
+f 377//1 378//1 362//1
+f 362//1 378//1 363//1
+f 378//1 379//1 363//1
+f 363//1 379//1 364//1
+f 379//1 380//1 364//1
+f 364//1 380//1 365//1
+f 380//1 381//1 365//1
+f 365//1 381//1 366//1
+f 381//1 382//1 366//1
+f 366//1 382//1 367//1
+f 382//1 383//1 367//1
+f 367//1 383//1 368//1
+f 383//1 384//1 368//1
+f 368//1 384//1 369//1
+f 384//1 385//1 369//1
+f 369//1 385//1 370//1
+f 385//1 386//1 370//1
+f 370//1 386//1 371//1
+f 386//1 387//1 371//1
+f 371//1 387//1 372//1
+f 387//1 388//1 372//1
+f 372//1 388//1 373//1
+f 388//1 389//1 373//1
+f 373//1 389//1 374//1
+f 389//1 390//1 374//1
+f 374//1 390//1 189//1
+f 390//1 188//1 189//1
+f 221//1 391//1 375//1
+f 391//1 392//1 375//1
+f 375//1 392//1 376//1
+f 392//1 393//1 376//1
+f 376//1 393//1 377//1
+f 393//1 394//1 377//1
+f 377//1 394//1 378//1
+f 394//1 395//1 378//1
+f 378//1 395//1 379//1
+f 395//1 396//1 379//1
+f 379//1 396//1 380//1
+f 396//1 397//1 380//1
+f 380//1 397//1 381//1
+f 397//1 398//1 381//1
+f 381//1 398//1 382//1
+f 398//1 399//1 382//1
+f 382//1 399//1 383//1
+f 399//1 400//1 383//1
+f 383//1 400//1 384//1
+f 400//1 401//1 384//1
+f 384//1 401//1 385//1
+f 401//1 402//1 385//1
+f 385//1 402//1 386//1
+f 402//1 403//1 386//1
+f 386//1 403//1 387//1
+f 403//1 404//1 387//1
+f 387//1 404//1 388//1
+f 404//1 405//1 388//1
+f 388//1 405//1 389//1
+f 405//1 406//1 389//1
+f 389//1 406//1 390//1
+f 406//1 407//1 390//1
+f 390//1 407//1 188//1
+f 407//1 187//1 188//1
+f 222//1 408//1 391//1
+f 408//1 409//1 391//1
+f 391//1 409//1 392//1
+f 409//1 410//1 392//1
+f 392//1 410//1 393//1
+f 410//1 411//1 393//1
+f 393//1 411//1 394//1
+f 411//1 412//1 394//1
+f 394//1 412//1 395//1
+f 412//1 413//1 395//1
+f 395//1 413//1 396//1
+f 413//1 414//1 396//1
+f 396//1 414//1 397//1
+f 414//1 415//1 397//1
+f 397//1 415//1 398//1
+f 415//1 416//1 398//1
+f 398//1 416//1 399//1
+f 416//1 417//1 399//1
+f 399//1 417//1 400//1
+f 417//1 418//1 400//1
+f 400//1 418//1 401//1
+f 418//1 419//1 401//1
+f 401//1 419//1 402//1
+f 419//1 420//1 402//1
+f 402//1 420//1 403//1
+f 420//1 421//1 403//1
+f 403//1 421//1 404//1
+f 421//1 422//1 404//1
+f 404//1 422//1 405//1
+f 422//1 423//1 405//1
+f 405//1 423//1 406//1
+f 423//1 424//1 406//1
+f 406//1 424//1 407//1
+f 424//1 425//1 407//1
+f 407//1 425//1 187//1
+f 425//1 186//1 187//1
+f 223//1 426//1 408//1
+f 426//1 427//1 408//1
+f 408//1 427//1 409//1
+f 427//1 428//1 409//1
+f 409//1 428//1 410//1
+f 428//1 429//1 410//1
+f 410//1 429//1 411//1
+f 429//1 430//1 411//1
+f 411//1 430//1 412//1
+f 430//1 431//1 412//1
+f 412//1 431//1 413//1
+f 431//1 432//1 413//1
+f 413//1 432//1 414//1
+f 432//1 433//1 414//1
+f 414//1 433//1 415//1
+f 433//1 434//1 415//1
+f 415//1 434//1 416//1
+f 434//1 435//1 416//1
+f 416//1 435//1 417//1
+f 435//1 436//1 417//1
+f 417//1 436//1 418//1
+f 436//1 437//1 418//1
+f 418//1 437//1 419//1
+f 437//1 438//1 419//1
+f 419//1 438//1 420//1
+f 438//1 439//1 420//1
+f 420//1 439//1 421//1
+f 439//1 440//1 421//1
+f 421//1 440//1 422//1
+f 440//1 441//1 422//1
+f 422//1 441//1 423//1
+f 441//1 442//1 423//1
+f 423//1 442//1 424//1
+f 442//1 443//1 424//1
+f 424//1 443//1 425//1
+f 443//1 444//1 425//1
+f 425//1 444//1 186//1
+f 444//1 185//1 186//1
+f 224//1 445//1 426//1
+f 445//1 446//1 426//1
+f 426//1 446//1 427//1
+f 446//1 447//1 427//1
+f 427//1 447//1 428//1
+f 447//1 448//1 428//1
+f 428//1 448//1 429//1
+f 448//1 449//1 429//1
+f 429//1 449//1 430//1
+f 449//1 450//1 430//1
+f 430//1 450//1 431//1
+f 450//1 451//1 431//1
+f 431//1 451//1 432//1
+f 451//1 452//1 432//1
+f 432//1 452//1 433//1
+f 452//1 453//1 433//1
+f 433//1 453//1 434//1
+f 453//1 454//1 434//1
+f 434//1 454//1 435//1
+f 454//1 455//1 435//1
+f 435//1 455//1 436//1
+f 455//1 456//1 436//1
+f 436//1 456//1 437//1
+f 456//1 457//1 437//1
+f 437//1 457//1 438//1
+f 457//1 458//1 438//1
+f 438//1 458//1 439//1
+f 458//1 459//1 439//1
+f 439//1 459//1 440//1
+f 459//1 460//1 440//1
+f 440//1 460//1 441//1
+f 460//1 461//1 441//1
+f 441//1 461//1 442//1
+f 461//1 462//1 442//1
+f 442//1 462//1 443//1
+f 462//1 463//1 443//1
+f 443//1 463//1 444//1
+f 463//1 464//1 444//1
+f 444//1 464//1 185//1
+f 464//1 184//1 185//1
+f 225//1 465//1 445//1
+f 465//1 466//1 445//1
+f 445//1 466//1 446//1
+f 466//1 467//1 446//1
+f 446//1 467//1 447//1
+f 467//1 468//1 447//1
+f 447//1 468//1 448//1
+f 468//1 469//1 448//1
+f 448//1 469//1 449//1
+f 469//1 470//1 449//1
+f 449//1 470//1 450//1
+f 470//1 471//1 450//1
+f 450//1 471//1 451//1
+f 471//1 472//1 451//1
+f 451//1 472//1 452//1
+f 472//1 473//1 452//1
+f 452//1 473//1 453//1
+f 473//1 474//1 453//1
+f 453//1 474//1 454//1
+f 474//1 475//1 454//1
+f 454//1 475//1 455//1
+f 475//1 476//1 455//1
+f 455//1 476//1 456//1
+f 476//1 477//1 456//1
+f 456//1 477//1 457//1
+f 477//1 478//1 457//1
+f 457//1 478//1 458//1
+f 478//1 479//1 458//1
+f 458//1 479//1 459//1
+f 479//1 480//1 459//1
+f 459//1 480//1 460//1
+f 480//1 481//1 460//1
+f 460//1 481//1 461//1
+f 481//1 482//1 461//1
+f 461//1 482//1 462//1
+f 482//1 483//1 462//1
+f 462//1 483//1 463//1
+f 483//1 484//1 463//1
+f 463//1 484//1 464//1
+f 484//1 485//1 464//1
+f 464//1 485//1 184//1
+f 485//1 183//1 184//1
+f 226//1 486//1 465//1
+f 486//1 487//1 465//1
+f 465//1 487//1 466//1
+f 487//1 488//1 466//1
+f 466//1 488//1 467//1
+f 488//1 489//1 467//1
+f 467//1 489//1 468//1
+f 489//1 490//1 468//1
+f 468//1 490//1 469//1
+f 490//1 491//1 469//1
+f 469//1 491//1 470//1
+f 491//1 492//1 470//1
+f 470//1 492//1 471//1
+f 492//1 493//1 471//1
+f 471//1 493//1 472//1
+f 493//1 494//1 472//1
+f 472//1 494//1 473//1
+f 494//1 495//1 473//1
+f 473//1 495//1 474//1
+f 495//1 496//1 474//1
+f 474//1 496//1 475//1
+f 496//1 497//1 475//1
+f 475//1 497//1 476//1
+f 497//1 498//1 476//1
+f 476//1 498//1 477//1
+f 498//1 499//1 477//1
+f 477//1 499//1 478//1
+f 499//1 500//1 478//1
+f 478//1 500//1 479//1
+f 500//1 501//1 479//1
+f 479//1 501//1 480//1
+f 501//1 502//1 480//1
+f 480//1 502//1 481//1
+f 502//1 503//1 481//1
+f 481//1 503//1 482//1
+f 503//1 504//1 482//1
+f 482//1 504//1 483//1
+f 504//1 505//1 483//1
+f 483//1 505//1 484//1
+f 505//1 506//1 484//1
+f 484//1 506//1 485//1
+f 506//1 507//1 485//1
+f 485//1 507//1 183//1
+f 507//1 182//1 183//1
+f 227//1 508//1 486//1
+f 508//1 509//1 486//1
+f 486//1 509//1 487//1
+f 509//1 510//1 487//1
+f 487//1 510//1 488//1
+f 510//1 511//1 488//1
+f 488//1 511//1 489//1
+f 511//1 512//1 489//1
+f 489//1 512//1 490//1
+f 512//1 513//1 490//1
+f 490//1 513//1 491//1
+f 513//1 514//1 491//1
+f 491//1 514//1 492//1
+f 514//1 515//1 492//1
+f 492//1 515//1 493//1
+f 515//1 516//1 493//1
+f 493//1 516//1 494//1
+f 516//1 517//1 494//1
+f 494//1 517//1 495//1
+f 517//1 518//1 495//1
+f 495//1 518//1 496//1
+f 518//1 519//1 496//1
+f 496//1 519//1 497//1
+f 519//1 520//1 497//1
+f 497//1 520//1 498//1
+f 520//1 521//1 498//1
+f 498//1 521//1 499//1
+f 521//1 522//1 499//1
+f 499//1 522//1 500//1
+f 522//1 523//1 500//1
+f 500//1 523//1 501//1
+f 523//1 524//1 501//1
+f 501//1 524//1 502//1
+f 524//1 525//1 502//1
+f 502//1 525//1 503//1
+f 525//1 526//1 503//1
+f 503//1 526//1 504//1
+f 526//1 527//1 504//1
+f 504//1 527//1 505//1
+f 527//1 528//1 505//1
+f 505//1 528//1 506//1
+f 528//1 529//1 506//1
+f 506//1 529//1 507//1
+f 529//1 530//1 507//1
+f 507//1 530//1 182//1
+f 530//1 181//1 182//1
+f 228//1 531//1 508//1
+f 531//1 532//1 508//1
+f 508//1 532//1 509//1
+f 532//1 533//1 509//1
+f 509//1 533//1 510//1
+f 533//1 534//1 510//1
+f 510//1 534//1 511//1
+f 534//1 535//1 511//1
+f 511//1 535//1 512//1
+f 535//1 536//1 512//1
+f 512//1 536//1 513//1
+f 536//1 537//1 513//1
+f 513//1 537//1 514//1
+f 537//1 538//1 514//1
+f 514//1 538//1 515//1
+f 538//1 539//1 515//1
+f 515//1 539//1 516//1
+f 539//1 540//1 516//1
+f 516//1 540//1 517//1
+f 540//1 541//1 517//1
+f 517//1 541//1 518//1
+f 541//1 542//1 518//1
+f 518//1 542//1 519//1
+f 542//1 543//1 519//1
+f 519//1 543//1 520//1
+f 543//1 544//1 520//1
+f 520//1 544//1 521//1
+f 544//1 545//1 521//1
+f 521//1 545//1 522//1
+f 545//1 546//1 522//1
+f 522//1 546//1 523//1
+f 546//1 547//1 523//1
+f 523//1 547//1 524//1
+f 547//1 548//1 524//1
+f 524//1 548//1 525//1
+f 548//1 549//1 525//1
+f 525//1 549//1 526//1
+f 549//1 550//1 526//1
+f 526//1 550//1 527//1
+f 550//1 551//1 527//1
+f 527//1 551//1 528//1
+f 551//1 552//1 528//1
+f 528//1 552//1 529//1
+f 552//1 553//1 529//1
+f 529//1 553//1 530//1
+f 553//1 554//1 530//1
+f 530//1 554//1 181//1
+f 554//1 180//1 181//1
+f 229//1 555//1 531//1
+f 555//1 556//1 531//1
+f 531//1 556//1 532//1
+f 556//1 557//1 532//1
+f 532//1 557//1 533//1
+f 557//1 558//1 533//1
+f 533//1 558//1 534//1
+f 558//1 559//1 534//1
+f 534//1 559//1 535//1
+f 559//1 560//1 535//1
+f 535//1 560//1 536//1
+f 560//1 561//1 536//1
+f 536//1 561//1 537//1
+f 561//1 562//1 537//1
+f 537//1 562//1 538//1
+f 562//1 563//1 538//1
+f 538//1 563//1 539//1
+f 563//1 564//1 539//1
+f 539//1 564//1 540//1
+f 564//1 565//1 540//1
+f 540//1 565//1 541//1
+f 565//1 566//1 541//1
+f 541//1 566//1 542//1
+f 566//1 567//1 542//1
+f 542//1 567//1 543//1
+f 567//1 568//1 543//1
+f 543//1 568//1 544//1
+f 568//1 569//1 544//1
+f 544//1 569//1 545//1
+f 569//1 570//1 545//1
+f 545//1 570//1 546//1
+f 570//1 571//1 546//1
+f 546//1 571//1 547//1
+f 571//1 572//1 547//1
+f 547//1 572//1 548//1
+f 572//1 573//1 548//1
+f 548//1 573//1 549//1
+f 573//1 574//1 549//1
+f 549//1 574//1 550//1
+f 574//1 575//1 550//1
+f 550//1 575//1 551//1
+f 575//1 576//1 551//1
+f 551//1 576//1 552//1
+f 576//1 577//1 552//1
+f 552//1 577//1 553//1
+f 577//1 578//1 553//1
+f 553//1 578//1 554//1
+f 578//1 579//1 554//1
+f 554//1 579//1 180//1
+f 579//1 179//1 180//1
+f 230//1 580//1 555//1
+f 580//1 581//1 555//1
+f 555//1 581//1 556//1
+f 581//1 582//1 556//1
+f 556//1 582//1 557//1
+f 582//1 583//1 557//1
+f 557//1 583//1 558//1
+f 583//1 584//1 558//1
+f 558//1 584//1 559//1
+f 584//1 585//1 559//1
+f 559//1 585//1 560//1
+f 585//1 586//1 560//1
+f 560//1 586//1 561//1
+f 586//1 587//1 561//1
+f 561//1 587//1 562//1
+f 587//1 588//1 562//1
+f 562//1 588//1 563//1
+f 588//1 589//1 563//1
+f 563//1 589//1 564//1
+f 589//1 590//1 564//1
+f 564//1 590//1 565//1
+f 590//1 591//1 565//1
+f 565//1 591//1 566//1
+f 591//1 592//1 566//1
+f 566//1 592//1 567//1
+f 592//1 593//1 567//1
+f 567//1 593//1 568//1
+f 593//1 594//1 568//1
+f 568//1 594//1 569//1
+f 594//1 595//1 569//1
+f 569//1 595//1 570//1
+f 595//1 596//1 570//1
+f 570//1 596//1 571//1
+f 596//1 597//1 571//1
+f 571//1 597//1 572//1
+f 597//1 598//1 572//1
+f 572//1 598//1 573//1
+f 598//1 599//1 573//1
+f 573//1 599//1 574//1
+f 599//1 600//1 574//1
+f 574//1 600//1 575//1
+f 600//1 601//1 575//1
+f 575//1 601//1 576//1
+f 601//1 602//1 576//1
+f 576//1 602//1 577//1
+f 602//1 603//1 577//1
+f 577//1 603//1 578//1
+f 603//1 604//1 578//1
+f 578//1 604//1 579//1
+f 604//1 605//1 579//1
+f 579//1 605//1 179//1
+f 605//1 178//1 179//1
+f 231//1 606//1 580//1
+f 606//1 607//1 580//1
+f 580//1 607//1 581//1
+f 607//1 608//1 581//1
+f 581//1 608//1 582//1
+f 608//1 609//1 582//1
+f 582//1 609//1 583//1
+f 609//1 610//1 583//1
+f 583//1 610//1 584//1
+f 610//1 611//1 584//1
+f 584//1 611//1 585//1
+f 611//1 612//1 585//1
+f 585//1 612//1 586//1
+f 612//1 613//1 586//1
+f 586//1 613//1 587//1
+f 613//1 614//1 587//1
+f 587//1 614//1 588//1
+f 614//1 615//1 588//1
+f 588//1 615//1 589//1
+f 615//1 616//1 589//1
+f 589//1 616//1 590//1
+f 616//1 617//1 590//1
+f 590//1 617//1 591//1
+f 617//1 618//1 591//1
+f 591//1 618//1 592//1
+f 618//1 619//1 592//1
+f 592//1 619//1 593//1
+f 619//1 620//1 593//1
+f 593//1 620//1 594//1
+f 620//1 621//1 594//1
+f 594//1 621//1 595//1
+f 621//1 622//1 595//1
+f 595//1 622//1 596//1
+f 622//1 623//1 596//1
+f 596//1 623//1 597//1
+f 623//1 624//1 597//1
+f 597//1 624//1 598//1
+f 624//1 625//1 598//1
+f 598//1 625//1 599//1
+f 625//1 626//1 599//1
+f 599//1 626//1 600//1
+f 626//1 627//1 600//1
+f 600//1 627//1 601//1
+f 627//1 628//1 601//1
+f 601//1 628//1 602//1
+f 628//1 629//1 602//1
+f 602//1 629//1 603//1
+f 629//1 630//1 603//1
+f 603//1 630//1 604//1
+f 630//1 631//1 604//1
+f 604//1 631//1 605//1
+f 631//1 632//1 605//1
+f 605//1 632//1 178//1
+f 632//1 177//1 178//1
+f 232//1 633//1 606//1
+f 633//1 634//1 606//1
+f 606//1 634//1 607//1
+f 634//1 635//1 607//1
+f 607//1 635//1 608//1
+f 635//1 636//1 608//1
+f 608//1 636//1 609//1
+f 636//1 637//1 609//1
+f 609//1 637//1 610//1
+f 637//1 638//1 610//1
+f 610//1 638//1 611//1
+f 638//1 639//1 611//1
+f 611//1 639//1 612//1
+f 639//1 640//1 612//1
+f 612//1 640//1 613//1
+f 640//1 641//1 613//1
+f 613//1 641//1 614//1
+f 641//1 642//1 614//1
+f 614//1 642//1 615//1
+f 642//1 643//1 615//1
+f 615//1 643//1 616//1
+f 643//1 644//1 616//1
+f 616//1 644//1 617//1
+f 644//1 645//1 617//1
+f 617//1 645//1 618//1
+f 645//1 646//1 618//1
+f 618//1 646//1 619//1
+f 646//1 647//1 619//1
+f 619//1 647//1 620//1
+f 647//1 648//1 620//1
+f 620//1 648//1 621//1
+f 648//1 649//1 621//1
+f 621//1 649//1 622//1
+f 649//1 650//1 622//1
+f 622//1 650//1 623//1
+f 650//1 651//1 623//1
+f 623//1 651//1 624//1
+f 651//1 652//1 624//1
+f 624//1 652//1 625//1
+f 652//1 653//1 625//1
+f 625//1 653//1 626//1
+f 653//1 654//1 626//1
+f 626//1 654//1 627//1
+f 654//1 655//1 627//1
+f 627//1 655//1 628//1
+f 655//1 656//1 628//1
+f 628//1 656//1 629//1
+f 656//1 657//1 629//1
+f 629//1 657//1 630//1
+f 657//1 658//1 630//1
+f 630//1 658//1 631//1
+f 658//1 659//1 631//1
+f 631//1 659//1 632//1
+f 659//1 660//1 632//1
+f 632//1 660//1 177//1
+f 660//1 176//1 177//1
+f 233//1 661//1 633//1
+f 661//1 662//1 633//1
+f 633//1 662//1 634//1
+f 662//1 663//1 634//1
+f 634//1 663//1 635//1
+f 663//1 664//1 635//1
+f 635//1 664//1 636//1
+f 664//1 665//1 636//1
+f 636//1 665//1 637//1
+f 665//1 666//1 637//1
+f 637//1 666//1 638//1
+f 666//1 667//1 638//1
+f 638//1 667//1 639//1
+f 667//1 668//1 639//1
+f 639//1 668//1 640//1
+f 668//1 669//1 640//1
+f 640//1 669//1 641//1
+f 669//1 670//1 641//1
+f 641//1 670//1 642//1
+f 670//1 671//1 642//1
+f 642//1 671//1 643//1
+f 671//1 672//1 643//1
+f 643//1 672//1 644//1
+f 672//1 673//1 644//1
+f 644//1 673//1 645//1
+f 673//1 674//1 645//1
+f 645//1 674//1 646//1
+f 674//1 675//1 646//1
+f 646//1 675//1 647//1
+f 675//1 676//1 647//1
+f 647//1 676//1 648//1
+f 676//1 677//1 648//1
+f 648//1 677//1 649//1
+f 677//1 678//1 649//1
+f 649//1 678//1 650//1
+f 678//1 679//1 650//1
+f 650//1 679//1 651//1
+f 679//1 680//1 651//1
+f 651//1 680//1 652//1
+f 680//1 681//1 652//1
+f 652//1 681//1 653//1
+f 681//1 682//1 653//1
+f 653//1 682//1 654//1
+f 682//1 683//1 654//1
+f 654//1 683//1 655//1
+f 683//1 684//1 655//1
+f 655//1 684//1 656//1
+f 684//1 685//1 656//1
+f 656//1 685//1 657//1
+f 685//1 686//1 657//1
+f 657//1 686//1 658//1
+f 686//1 687//1 658//1
+f 658//1 687//1 659//1
+f 687//1 688//1 659//1
+f 659//1 688//1 660//1
+f 688//1 689//1 660//1
+f 660//1 689//1 176//1
+f 689//1 175//1 176//1
+f 234//1 690//1 661//1
+f 690//1 691//1 661//1
+f 661//1 691//1 662//1
+f 691//1 692//1 662//1
+f 662//1 692//1 663//1
+f 692//1 693//1 663//1
+f 663//1 693//1 664//1
+f 693//1 694//1 664//1
+f 664//1 694//1 665//1
+f 694//1 695//1 665//1
+f 665//1 695//1 666//1
+f 695//1 696//1 666//1
+f 666//1 696//1 667//1
+f 696//1 697//1 667//1
+f 667//1 697//1 668//1
+f 697//1 698//1 668//1
+f 668//1 698//1 669//1
+f 698//1 699//1 669//1
+f 669//1 699//1 670//1
+f 699//1 700//1 670//1
+f 670//1 700//1 671//1
+f 700//1 701//1 671//1
+f 671//1 701//1 672//1
+f 701//1 702//1 672//1
+f 672//1 702//1 673//1
+f 702//1 703//1 673//1
+f 673//1 703//1 674//1
+f 703//1 704//1 674//1
+f 674//1 704//1 675//1
+f 704//1 705//1 675//1
+f 675//1 705//1 676//1
+f 705//1 706//1 676//1
+f 676//1 706//1 677//1
+f 706//1 707//1 677//1
+f 677//1 707//1 678//1
+f 707//1 708//1 678//1
+f 678//1 708//1 679//1
+f 708//1 709//1 679//1
+f 679//1 709//1 680//1
+f 709//1 710//1 680//1
+f 680//1 710//1 681//1
+f 710//1 711//1 681//1
+f 681//1 711//1 682//1
+f 711//1 712//1 682//1
+f 682//1 712//1 683//1
+f 712//1 713//1 683//1
+f 683//1 713//1 684//1
+f 713//1 714//1 684//1
+f 684//1 714//1 685//1
+f 714//1 715//1 685//1
+f 685//1 715//1 686//1
+f 715//1 716//1 686//1
+f 686//1 716//1 687//1
+f 716//1 717//1 687//1
+f 687//1 717//1 688//1
+f 717//1 718//1 688//1
+f 688//1 718//1 689//1
+f 718//1 719//1 689//1
+f 689//1 719//1 175//1
+f 719//1 174//1 175//1
+f 235//1 720//1 690//1
+f 720//1 721//1 690//1
+f 690//1 721//1 691//1
+f 721//1 722//1 691//1
+f 691//1 722//1 692//1
+f 722//1 723//1 692//1
+f 692//1 723//1 693//1
+f 723//1 724//1 693//1
+f 693//1 724//1 694//1
+f 724//1 725//1 694//1
+f 694//1 725//1 695//1
+f 725//1 726//1 695//1
+f 695//1 726//1 696//1
+f 726//1 727//1 696//1
+f 696//1 727//1 697//1
+f 727//1 728//1 697//1
+f 697//1 728//1 698//1
+f 728//1 729//1 698//1
+f 698//1 729//1 699//1
+f 729//1 730//1 699//1
+f 699//1 730//1 700//1
+f 730//1 731//1 700//1
+f 700//1 731//1 701//1
+f 731//1 732//1 701//1
+f 701//1 732//1 702//1
+f 732//1 733//1 702//1
+f 702//1 733//1 703//1
+f 733//1 734//1 703//1
+f 703//1 734//1 704//1
+f 734//1 735//1 704//1
+f 704//1 735//1 705//1
+f 735//1 736//1 705//1
+f 705//1 736//1 706//1
+f 736//1 737//1 706//1
+f 706//1 737//1 707//1
+f 737//1 738//1 707//1
+f 707//1 738//1 708//1
+f 738//1 739//1 708//1
+f 708//1 739//1 709//1
+f 739//1 740//1 709//1
+f 709//1 740//1 710//1
+f 740//1 741//1 710//1
+f 710//1 741//1 711//1
+f 741//1 742//1 711//1
+f 711//1 742//1 712//1
+f 742//1 743//1 712//1
+f 712//1 743//1 713//1
+f 743//1 744//1 713//1
+f 713//1 744//1 714//1
+f 744//1 745//1 714//1
+f 714//1 745//1 715//1
+f 745//1 746//1 715//1
+f 715//1 746//1 716//1
+f 746//1 747//1 716//1
+f 716//1 747//1 717//1
+f 747//1 748//1 717//1
+f 717//1 748//1 718//1
+f 748//1 749//1 718//1
+f 718//1 749//1 719//1
+f 749//1 750//1 719//1
+f 719//1 750//1 174//1
+f 750//1 173//1 174//1
+f 236//1 751//1 720//1
+f 751//1 752//1 720//1
+f 720//1 752//1 721//1
+f 752//1 753//1 721//1
+f 721//1 753//1 722//1
+f 753//1 754//1 722//1
+f 722//1 754//1 723//1
+f 754//1 755//1 723//1
+f 723//1 755//1 724//1
+f 755//1 756//1 724//1
+f 724//1 756//1 725//1
+f 756//1 757//1 725//1
+f 725//1 757//1 726//1
+f 757//1 758//1 726//1
+f 726//1 758//1 727//1
+f 758//1 759//1 727//1
+f 727//1 759//1 728//1
+f 759//1 760//1 728//1
+f 728//1 760//1 729//1
+f 760//1 761//1 729//1
+f 729//1 761//1 730//1
+f 761//1 762//1 730//1
+f 730//1 762//1 731//1
+f 762//1 763//1 731//1
+f 731//1 763//1 732//1
+f 763//1 764//1 732//1
+f 732//1 764//1 733//1
+f 764//1 765//1 733//1
+f 733//1 765//1 734//1
+f 765//1 766//1 734//1
+f 734//1 766//1 735//1
+f 766//1 767//1 735//1
+f 735//1 767//1 736//1
+f 767//1 768//1 736//1
+f 736//1 768//1 737//1
+f 768//1 769//1 737//1
+f 737//1 769//1 738//1
+f 769//1 770//1 738//1
+f 738//1 770//1 739//1
+f 770//1 771//1 739//1
+f 739//1 771//1 740//1
+f 771//1 772//1 740//1
+f 740//1 772//1 741//1
+f 772//1 773//1 741//1
+f 741//1 773//1 742//1
+f 773//1 774//1 742//1
+f 742//1 774//1 743//1
+f 774//1 775//1 743//1
+f 743//1 775//1 744//1
+f 775//1 776//1 744//1
+f 744//1 776//1 745//1
+f 776//1 777//1 745//1
+f 745//1 777//1 746//1
+f 777//1 778//1 746//1
+f 746//1 778//1 747//1
+f 778//1 779//1 747//1
+f 747//1 779//1 748//1
+f 779//1 780//1 748//1
+f 748//1 780//1 749//1
+f 780//1 781//1 749//1
+f 749//1 781//1 750//1
+f 781//1 782//1 750//1
+f 750//1 782//1 173//1
+f 782//1 172//1 173//1
+f 237//1 783//1 751//1
+f 783//1 784//1 751//1
+f 751//1 784//1 752//1
+f 784//1 785//1 752//1
+f 752//1 785//1 753//1
+f 785//1 786//1 753//1
+f 753//1 786//1 754//1
+f 786//1 787//1 754//1
+f 754//1 787//1 755//1
+f 787//1 788//1 755//1
+f 755//1 788//1 756//1
+f 788//1 789//1 756//1
+f 756//1 789//1 757//1
+f 789//1 790//1 757//1
+f 757//1 790//1 758//1
+f 790//1 791//1 758//1
+f 758//1 791//1 759//1
+f 791//1 792//1 759//1
+f 759//1 792//1 760//1
+f 792//1 793//1 760//1
+f 760//1 793//1 761//1
+f 793//1 794//1 761//1
+f 761//1 794//1 762//1
+f 794//1 795//1 762//1
+f 762//1 795//1 763//1
+f 795//1 796//1 763//1
+f 763//1 796//1 764//1
+f 796//1 797//1 764//1
+f 764//1 797//1 765//1
+f 797//1 798//1 765//1
+f 765//1 798//1 766//1
+f 798//1 799//1 766//1
+f 766//1 799//1 767//1
+f 799//1 800//1 767//1
+f 767//1 800//1 768//1
+f 800//1 801//1 768//1
+f 768//1 801//1 769//1
+f 801//1 802//1 769//1
+f 769//1 802//1 770//1
+f 802//1 803//1 770//1
+f 770//1 803//1 771//1
+f 803//1 804//1 771//1
+f 771//1 804//1 772//1
+f 804//1 805//1 772//1
+f 772//1 805//1 773//1
+f 805//1 806//1 773//1
+f 773//1 806//1 774//1
+f 806//1 807//1 774//1
+f 774//1 807//1 775//1
+f 807//1 808//1 775//1
+f 775//1 808//1 776//1
+f 808//1 809//1 776//1
+f 776//1 809//1 777//1
+f 809//1 810//1 777//1
+f 777//1 810//1 778//1
+f 810//1 811//1 778//1
+f 778//1 811//1 779//1
+f 811//1 812//1 779//1
+f 779//1 812//1 780//1
+f 812//1 813//1 780//1
+f 780//1 813//1 781//1
+f 813//1 814//1 781//1
+f 781//1 814//1 782//1
+f 814//1 815//1 782//1
+f 782//1 815//1 172//1
+f 815//1 171//1 172//1
+f 238//1 816//1 783//1
+f 816//1 817//1 783//1
+f 783//1 817//1 784//1
+f 817//1 818//1 784//1
+f 784//1 818//1 785//1
+f 818//1 819//1 785//1
+f 785//1 819//1 786//1
+f 819//1 820//1 786//1
+f 786//1 820//1 787//1
+f 820//1 821//1 787//1
+f 787//1 821//1 788//1
+f 821//1 822//1 788//1
+f 788//1 822//1 789//1
+f 822//1 823//1 789//1
+f 789//1 823//1 790//1
+f 823//1 824//1 790//1
+f 790//1 824//1 791//1
+f 824//1 825//1 791//1
+f 791//1 825//1 792//1
+f 825//1 826//1 792//1
+f 792//1 826//1 793//1
+f 826//1 827//1 793//1
+f 793//1 827//1 794//1
+f 827//1 828//1 794//1
+f 794//1 828//1 795//1
+f 828//1 829//1 795//1
+f 795//1 829//1 796//1
+f 829//1 830//1 796//1
+f 796//1 830//1 797//1
+f 830//1 831//1 797//1
+f 797//1 831//1 798//1
+f 831//1 832//1 798//1
+f 798//1 832//1 799//1
+f 832//1 833//1 799//1
+f 799//1 833//1 800//1
+f 833//1 834//1 800//1
+f 800//1 834//1 801//1
+f 834//1 835//1 801//1
+f 801//1 835//1 802//1
+f 835//1 836//1 802//1
+f 802//1 836//1 803//1
+f 836//1 837//1 803//1
+f 803//1 837//1 804//1
+f 837//1 838//1 804//1
+f 804//1 838//1 805//1
+f 838//1 839//1 805//1
+f 805//1 839//1 806//1
+f 839//1 840//1 806//1
+f 806//1 840//1 807//1
+f 840//1 841//1 807//1
+f 807//1 841//1 808//1
+f 841//1 842//1 808//1
+f 808//1 842//1 809//1
+f 842//1 843//1 809//1
+f 809//1 843//1 810//1
+f 843//1 844//1 810//1
+f 810//1 844//1 811//1
+f 844//1 845//1 811//1
+f 811//1 845//1 812//1
+f 845//1 846//1 812//1
+f 812//1 846//1 813//1
+f 846//1 847//1 813//1
+f 813//1 847//1 814//1
+f 847//1 848//1 814//1
+f 814//1 848//1 815//1
+f 848//1 849//1 815//1
+f 815//1 849//1 171//1
+f 849//1 170//1 171//1
+f 239//1 850//1 816//1
+f 850//1 851//1 816//1
+f 816//1 851//1 817//1
+f 851//1 852//1 817//1
+f 817//1 852//1 818//1
+f 852//1 853//1 818//1
+f 818//1 853//1 819//1
+f 853//1 854//1 819//1
+f 819//1 854//1 820//1
+f 854//1 855//1 820//1
+f 820//1 855//1 821//1
+f 855//1 856//1 821//1
+f 821//1 856//1 822//1
+f 856//1 857//1 822//1
+f 822//1 857//1 823//1
+f 857//1 858//1 823//1
+f 823//1 858//1 824//1
+f 858//1 859//1 824//1
+f 824//1 859//1 825//1
+f 859//1 860//1 825//1
+f 825//1 860//1 826//1
+f 860//1 861//1 826//1
+f 826//1 861//1 827//1
+f 861//1 862//1 827//1
+f 827//1 862//1 828//1
+f 862//1 863//1 828//1
+f 828//1 863//1 829//1
+f 863//1 864//1 829//1
+f 829//1 864//1 830//1
+f 864//1 865//1 830//1
+f 830//1 865//1 831//1
+f 865//1 866//1 831//1
+f 831//1 866//1 832//1
+f 866//1 867//1 832//1
+f 832//1 867//1 833//1
+f 867//1 868//1 833//1
+f 833//1 868//1 834//1
+f 868//1 869//1 834//1
+f 834//1 869//1 835//1
+f 869//1 870//1 835//1
+f 835//1 870//1 836//1
+f 870//1 871//1 836//1
+f 836//1 871//1 837//1
+f 871//1 872//1 837//1
+f 837//1 872//1 838//1
+f 872//1 873//1 838//1
+f 838//1 873//1 839//1
+f 873//1 874//1 839//1
+f 839//1 874//1 840//1
+f 874//1 875//1 840//1
+f 840//1 875//1 841//1
+f 875//1 876//1 841//1
+f 841//1 876//1 842//1
+f 876//1 877//1 842//1
+f 842//1 877//1 843//1
+f 877//1 878//1 843//1
+f 843//1 878//1 844//1
+f 878//1 879//1 844//1
+f 844//1 879//1 845//1
+f 879//1 880//1 845//1
+f 845//1 880//1 846//1
+f 880//1 881//1 846//1
+f 846//1 881//1 847//1
+f 881//1 882//1 847//1
+f 847//1 882//1 848//1
+f 882//1 883//1 848//1
+f 848//1 883//1 849//1
+f 883//1 884//1 849//1
+f 849//1 884//1 170//1
+f 884//1 169//1 170//1
+f 240//1 885//1 850//1
+f 885//1 886//1 850//1
+f 850//1 886//1 851//1
+f 886//1 887//1 851//1
+f 851//1 887//1 852//1
+f 887//1 888//1 852//1
+f 852//1 888//1 853//1
+f 888//1 889//1 853//1
+f 853//1 889//1 854//1
+f 889//1 890//1 854//1
+f 854//1 890//1 855//1
+f 890//1 891//1 855//1
+f 855//1 891//1 856//1
+f 891//1 892//1 856//1
+f 856//1 892//1 857//1
+f 892//1 893//1 857//1
+f 857//1 893//1 858//1
+f 893//1 894//1 858//1
+f 858//1 894//1 859//1
+f 894//1 895//1 859//1
+f 859//1 895//1 860//1
+f 895//1 896//1 860//1
+f 860//1 896//1 861//1
+f 896//1 897//1 861//1
+f 861//1 897//1 862//1
+f 897//1 898//1 862//1
+f 862//1 898//1 863//1
+f 898//1 899//1 863//1
+f 863//1 899//1 864//1
+f 899//1 900//1 864//1
+f 864//1 900//1 865//1
+f 900//1 901//1 865//1
+f 865//1 901//1 866//1
+f 901//1 902//1 866//1
+f 866//1 902//1 867//1
+f 902//1 903//1 867//1
+f 867//1 903//1 868//1
+f 903//1 904//1 868//1
+f 868//1 904//1 869//1
+f 904//1 905//1 869//1
+f 869//1 905//1 870//1
+f 905//1 906//1 870//1
+f 870//1 906//1 871//1
+f 906//1 907//1 871//1
+f 871//1 907//1 872//1
+f 907//1 908//1 872//1
+f 872//1 908//1 873//1
+f 908//1 909//1 873//1
+f 873//1 909//1 874//1
+f 909//1 910//1 874//1
+f 874//1 910//1 875//1
+f 910//1 911//1 875//1
+f 875//1 911//1 876//1
+f 911//1 912//1 876//1
+f 876//1 912//1 877//1
+f 912//1 913//1 877//1
+f 877//1 913//1 878//1
+f 913//1 914//1 878//1
+f 878//1 914//1 879//1
+f 914//1 915//1 879//1
+f 879//1 915//1 880//1
+f 915//1 916//1 880//1
+f 880//1 916//1 881//1
+f 916//1 917//1 881//1
+f 881//1 917//1 882//1
+f 917//1 918//1 882//1
+f 882//1 918//1 883//1
+f 918//1 919//1 883//1
+f 883//1 919//1 884//1
+f 919//1 920//1 884//1
+f 884//1 920//1 169//1
+f 920//1 168//1 169//1
+f 241//1 921//1 885//1
+f 921//1 922//1 885//1
+f 885//1 922//1 886//1
+f 922//1 923//1 886//1
+f 886//1 923//1 887//1
+f 923//1 924//1 887//1
+f 887//1 924//1 888//1
+f 924//1 925//1 888//1
+f 888//1 925//1 889//1
+f 925//1 926//1 889//1
+f 889//1 926//1 890//1
+f 926//1 927//1 890//1
+f 890//1 927//1 891//1
+f 927//1 928//1 891//1
+f 891//1 928//1 892//1
+f 928//1 929//1 892//1
+f 892//1 929//1 893//1
+f 929//1 930//1 893//1
+f 893//1 930//1 894//1
+f 930//1 931//1 894//1
+f 894//1 931//1 895//1
+f 931//1 932//1 895//1
+f 895//1 932//1 896//1
+f 932//1 933//1 896//1
+f 896//1 933//1 897//1
+f 933//1 934//1 897//1
+f 897//1 934//1 898//1
+f 934//1 935//1 898//1
+f 898//1 935//1 899//1
+f 935//1 936//1 899//1
+f 899//1 936//1 900//1
+f 936//1 937//1 900//1
+f 900//1 937//1 901//1
+f 937//1 938//1 901//1
+f 901//1 938//1 902//1
+f 938//1 939//1 902//1
+f 902//1 939//1 903//1
+f 939//1 940//1 903//1
+f 903//1 940//1 904//1
+f 940//1 941//1 904//1
+f 904//1 941//1 905//1
+f 941//1 942//1 905//1
+f 905//1 942//1 906//1
+f 942//1 943//1 906//1
+f 906//1 943//1 907//1
+f 943//1 944//1 907//1
+f 907//1 944//1 908//1
+f 944//1 945//1 908//1
+f 908//1 945//1 909//1
+f 945//1 946//1 909//1
+f 909//1 946//1 910//1
+f 946//1 947//1 910//1
+f 910//1 947//1 911//1
+f 947//1 948//1 911//1
+f 911//1 948//1 912//1
+f 948//1 949//1 912//1
+f 912//1 949//1 913//1
+f 949//1 950//1 913//1
+f 913//1 950//1 914//1
+f 950//1 951//1 914//1
+f 914//1 951//1 915//1
+f 951//1 952//1 915//1
+f 915//1 952//1 916//1
+f 952//1 953//1 916//1
+f 916//1 953//1 917//1
+f 953//1 954//1 917//1
+f 917//1 954//1 918//1
+f 954//1 955//1 918//1
+f 918//1 955//1 919//1
+f 955//1 956//1 919//1
+f 919//1 956//1 920//1
+f 956//1 957//1 920//1
+f 920//1 957//1 168//1
+f 957//1 167//1 168//1
+f 242//1 958//1 921//1
+f 958//1 959//1 921//1
+f 921//1 959//1 922//1
+f 959//1 960//1 922//1
+f 922//1 960//1 923//1
+f 960//1 961//1 923//1
+f 923//1 961//1 924//1
+f 961//1 962//1 924//1
+f 924//1 962//1 925//1
+f 962//1 963//1 925//1
+f 925//1 963//1 926//1
+f 963//1 964//1 926//1
+f 926//1 964//1 927//1
+f 964//1 965//1 927//1
+f 927//1 965//1 928//1
+f 965//1 966//1 928//1
+f 928//1 966//1 929//1
+f 966//1 967//1 929//1
+f 929//1 967//1 930//1
+f 967//1 968//1 930//1
+f 930//1 968//1 931//1
+f 968//1 969//1 931//1
+f 931//1 969//1 932//1
+f 969//1 970//1 932//1
+f 932//1 970//1 933//1
+f 970//1 971//1 933//1
+f 933//1 971//1 934//1
+f 971//1 972//1 934//1
+f 934//1 972//1 935//1
+f 972//1 973//1 935//1
+f 935//1 973//1 936//1
+f 973//1 974//1 936//1
+f 936//1 974//1 937//1
+f 974//1 975//1 937//1
+f 937//1 975//1 938//1
+f 975//1 976//1 938//1
+f 938//1 976//1 939//1
+f 976//1 977//1 939//1
+f 939//1 977//1 940//1
+f 977//1 978//1 940//1
+f 940//1 978//1 941//1
+f 978//1 979//1 941//1
+f 941//1 979//1 942//1
+f 979//1 980//1 942//1
+f 942//1 980//1 943//1
+f 980//1 981//1 943//1
+f 943//1 981//1 944//1
+f 981//1 982//1 944//1
+f 944//1 982//1 945//1
+f 982//1 983//1 945//1
+f 945//1 983//1 946//1
+f 983//1 984//1 946//1
+f 946//1 984//1 947//1
+f 984//1 985//1 947//1
+f 947//1 985//1 948//1
+f 985//1 986//1 948//1
+f 948//1 986//1 949//1
+f 986//1 987//1 949//1
+f 949//1 987//1 950//1
+f 987//1 988//1 950//1
+f 950//1 988//1 951//1
+f 988//1 989//1 951//1
+f 951//1 989//1 952//1
+f 989//1 990//1 952//1
+f 952//1 990//1 953//1
+f 990//1 991//1 953//1
+f 953//1 991//1 954//1
+f 991//1 992//1 954//1
+f 954//1 992//1 955//1
+f 992//1 993//1 955//1
+f 955//1 993//1 956//1
+f 993//1 994//1 956//1
+f 956//1 994//1 957//1
+f 994//1 995//1 957//1
+f 957//1 995//1 167//1
+f 995//1 166//1 167//1
+f 243//1 996//1 958//1
+f 996//1 997//1 958//1
+f 958//1 997//1 959//1
+f 997//1 998//1 959//1
+f 959//1 998//1 960//1
+f 998//1 999//1 960//1
+f 960//1 999//1 961//1
+f 999//1 1000//1 961//1
+f 961//1 1000//1 962//1
+f 1000//1 1001//1 962//1
+f 962//1 1001//1 963//1
+f 1001//1 1002//1 963//1
+f 963//1 1002//1 964//1
+f 1002//1 1003//1 964//1
+f 964//1 1003//1 965//1
+f 1003//1 1004//1 965//1
+f 965//1 1004//1 966//1
+f 1004//1 1005//1 966//1
+f 966//1 1005//1 967//1
+f 1005//1 1006//1 967//1
+f 967//1 1006//1 968//1
+f 1006//1 1007//1 968//1
+f 968//1 1007//1 969//1
+f 1007//1 1008//1 969//1
+f 969//1 1008//1 970//1
+f 1008//1 1009//1 970//1
+f 970//1 1009//1 971//1
+f 1009//1 1010//1 971//1
+f 971//1 1010//1 972//1
+f 1010//1 1011//1 972//1
+f 972//1 1011//1 973//1
+f 1011//1 1012//1 973//1
+f 973//1 1012//1 974//1
+f 1012//1 1013//1 974//1
+f 974//1 1013//1 975//1
+f 1013//1 1014//1 975//1
+f 975//1 1014//1 976//1
+f 1014//1 1015//1 976//1
+f 976//1 1015//1 977//1
+f 1015//1 1016//1 977//1
+f 977//1 1016//1 978//1
+f 1016//1 1017//1 978//1
+f 978//1 1017//1 979//1
+f 1017//1 1018//1 979//1
+f 979//1 1018//1 980//1
+f 1018//1 1019//1 980//1
+f 980//1 1019//1 981//1
+f 1019//1 1020//1 981//1
+f 981//1 1020//1 982//1
+f 1020//1 1021//1 982//1
+f 982//1 1021//1 983//1
+f 1021//1 1022//1 983//1
+f 983//1 1022//1 984//1
+f 1022//1 1023//1 984//1
+f 984//1 1023//1 985//1
+f 1023//1 1024//1 985//1
+f 985//1 1024//1 986//1
+f 1024//1 1025//1 986//1
+f 986//1 1025//1 987//1
+f 1025//1 1026//1 987//1
+f 987//1 1026//1 988//1
+f 1026//1 1027//1 988//1
+f 988//1 1027//1 989//1
+f 1027//1 1028//1 989//1
+f 989//1 1028//1 990//1
+f 1028//1 1029//1 990//1
+f 990//1 1029//1 991//1
+f 1029//1 1030//1 991//1
+f 991//1 1030//1 992//1
+f 1030//1 1031//1 992//1
+f 992//1 1031//1 993//1
+f 1031//1 1032//1 993//1
+f 993//1 1032//1 994//1
+f 1032//1 1033//1 994//1
+f 994//1 1033//1 995//1
+f 1033//1 1034//1 995//1
+f 995//1 1034//1 166//1
+f 1034//1 165//1 166//1
+f 244//1 1035//1 996//1
+f 1035//1 1036//1 996//1
+f 996//1 1036//1 997//1
+f 1036//1 1037//1 997//1
+f 997//1 1037//1 998//1
+f 1037//1 1038//1 998//1
+f 998//1 1038//1 999//1
+f 1038//1 1039//1 999//1
+f 999//1 1039//1 1000//1
+f 1039//1 1040//1 1000//1
+f 1000//1 1040//1 1001//1
+f 1040//1 1041//1 1001//1
+f 1001//1 1041//1 1002//1
+f 1041//1 1042//1 1002//1
+f 1002//1 1042//1 1003//1
+f 1042//1 1043//1 1003//1
+f 1003//1 1043//1 1004//1
+f 1043//1 1044//1 1004//1
+f 1004//1 1044//1 1005//1
+f 1044//1 1045//1 1005//1
+f 1005//1 1045//1 1006//1
+f 1045//1 1046//1 1006//1
+f 1006//1 1046//1 1007//1
+f 1046//1 1047//1 1007//1
+f 1007//1 1047//1 1008//1
+f 1047//1 1048//1 1008//1
+f 1008//1 1048//1 1009//1
+f 1048//1 1049//1 1009//1
+f 1009//1 1049//1 1010//1
+f 1049//1 1050//1 1010//1
+f 1010//1 1050//1 1011//1
+f 1050//1 1051//1 1011//1
+f 1011//1 1051//1 1012//1
+f 1051//1 1052//1 1012//1
+f 1012//1 1052//1 1013//1
+f 1052//1 1053//1 1013//1
+f 1013//1 1053//1 1014//1
+f 1053//1 1054//1 1014//1
+f 1014//1 1054//1 1015//1
+f 1054//1 1055//1 1015//1
+f 1015//1 1055//1 1016//1
+f 1055//1 1056//1 1016//1
+f 1016//1 1056//1 1017//1
+f 1056//1 1057//1 1017//1
+f 1017//1 1057//1 1018//1
+f 1057//1 1058//1 1018//1
+f 1018//1 1058//1 1019//1
+f 1058//1 1059//1 1019//1
+f 1019//1 1059//1 1020//1
+f 1059//1 1060//1 1020//1
+f 1020//1 1060//1 1021//1
+f 1060//1 1061//1 1021//1
+f 1021//1 1061//1 1022//1
+f 1061//1 1062//1 1022//1
+f 1022//1 1062//1 1023//1
+f 1062//1 1063//1 1023//1
+f 1023//1 1063//1 1024//1
+f 1063//1 1064//1 1024//1
+f 1024//1 1064//1 1025//1
+f 1064//1 1065//1 1025//1
+f 1025//1 1065//1 1026//1
+f 1065//1 1066//1 1026//1
+f 1026//1 1066//1 1027//1
+f 1066//1 1067//1 1027//1
+f 1027//1 1067//1 1028//1
+f 1067//1 1068//1 1028//1
+f 1028//1 1068//1 1029//1
+f 1068//1 1069//1 1029//1
+f 1029//1 1069//1 1030//1
+f 1069//1 1070//1 1030//1
+f 1030//1 1070//1 1031//1
+f 1070//1 1071//1 1031//1
+f 1031//1 1071//1 1032//1
+f 1071//1 1072//1 1032//1
+f 1032//1 1072//1 1033//1
+f 1072//1 1073//1 1033//1
+f 1033//1 1073//1 1034//1
+f 1073//1 1074//1 1034//1
+f 1034//1 1074//1 165//1
+f 1074//1 164//1 165//1
+f 245//1 1075//1 1035//1
+f 1075//1 1076//1 1035//1
+f 1035//1 1076//1 1036//1
+f 1076//1 1077//1 1036//1
+f 1036//1 1077//1 1037//1
+f 1077//1 1078//1 1037//1
+f 1037//1 1078//1 1038//1
+f 1078//1 1079//1 1038//1
+f 1038//1 1079//1 1039//1
+f 1079//1 1080//1 1039//1
+f 1039//1 1080//1 1040//1
+f 1080//1 1081//1 1040//1
+f 1040//1 1081//1 1041//1
+f 1081//1 1082//1 1041//1
+f 1041//1 1082//1 1042//1
+f 1082//1 1083//1 1042//1
+f 1042//1 1083//1 1043//1
+f 1083//1 1084//1 1043//1
+f 1043//1 1084//1 1044//1
+f 1084//1 1085//1 1044//1
+f 1044//1 1085//1 1045//1
+f 1085//1 1086//1 1045//1
+f 1045//1 1086//1 1046//1
+f 1086//1 1087//1 1046//1
+f 1046//1 1087//1 1047//1
+f 1087//1 1088//1 1047//1
+f 1047//1 1088//1 1048//1
+f 1088//1 1089//1 1048//1
+f 1048//1 1089//1 1049//1
+f 1089//1 1090//1 1049//1
+f 1049//1 1090//1 1050//1
+f 1090//1 1091//1 1050//1
+f 1050//1 1091//1 1051//1
+f 1091//1 1092//1 1051//1
+f 1051//1 1092//1 1052//1
+f 1092//1 1093//1 1052//1
+f 1052//1 1093//1 1053//1
+f 1093//1 1094//1 1053//1
+f 1053//1 1094//1 1054//1
+f 1094//1 1095//1 1054//1
+f 1054//1 1095//1 1055//1
+f 1095//1 1096//1 1055//1
+f 1055//1 1096//1 1056//1
+f 1096//1 1097//1 1056//1
+f 1056//1 1097//1 1057//1
+f 1097//1 1098//1 1057//1
+f 1057//1 1098//1 1058//1
+f 1098//1 1099//1 1058//1
+f 1058//1 1099//1 1059//1
+f 1099//1 1100//1 1059//1
+f 1059//1 1100//1 1060//1
+f 1100//1 1101//1 1060//1
+f 1060//1 1101//1 1061//1
+f 1101//1 1102//1 1061//1
+f 1061//1 1102//1 1062//1
+f 1102//1 1103//1 1062//1
+f 1062//1 1103//1 1063//1
+f 1103//1 1104//1 1063//1
+f 1063//1 1104//1 1064//1
+f 1104//1 1105//1 1064//1
+f 1064//1 1105//1 1065//1
+f 1105//1 1106//1 1065//1
+f 1065//1 1106//1 1066//1
+f 1106//1 1107//1 1066//1
+f 1066//1 1107//1 1067//1
+f 1107//1 1108//1 1067//1
+f 1067//1 1108//1 1068//1
+f 1108//1 1109//1 1068//1
+f 1068//1 1109//1 1069//1
+f 1109//1 1110//1 1069//1
+f 1069//1 1110//1 1070//1
+f 1110//1 1111//1 1070//1
+f 1070//1 1111//1 1071//1
+f 1111//1 1112//1 1071//1
+f 1071//1 1112//1 1072//1
+f 1112//1 1113//1 1072//1
+f 1072//1 1113//1 1073//1
+f 1113//1 1114//1 1073//1
+f 1073//1 1114//1 1074//1
+f 1114//1 1115//1 1074//1
+f 1074//1 1115//1 164//1
+f 1115//1 163//1 164//1
+f 246//1 1116//1 1075//1
+f 1116//1 1117//1 1075//1
+f 1075//1 1117//1 1076//1
+f 1117//1 1118//1 1076//1
+f 1076//1 1118//1 1077//1
+f 1118//1 1119//1 1077//1
+f 1077//1 1119//1 1078//1
+f 1119//1 1120//1 1078//1
+f 1078//1 1120//1 1079//1
+f 1120//1 1121//1 1079//1
+f 1079//1 1121//1 1080//1
+f 1121//1 1122//1 1080//1
+f 1080//1 1122//1 1081//1
+f 1122//1 1123//1 1081//1
+f 1081//1 1123//1 1082//1
+f 1123//1 1124//1 1082//1
+f 1082//1 1124//1 1083//1
+f 1124//1 1125//1 1083//1
+f 1083//1 1125//1 1084//1
+f 1125//1 1126//1 1084//1
+f 1084//1 1126//1 1085//1
+f 1126//1 1127//1 1085//1
+f 1085//1 1127//1 1086//1
+f 1127//1 1128//1 1086//1
+f 1086//1 1128//1 1087//1
+f 1128//1 1129//1 1087//1
+f 1087//1 1129//1 1088//1
+f 1129//1 1130//1 1088//1
+f 1088//1 1130//1 1089//1
+f 1130//1 1131//1 1089//1
+f 1089//1 1131//1 1090//1
+f 1131//1 1132//1 1090//1
+f 1090//1 1132//1 1091//1
+f 1132//1 1133//1 1091//1
+f 1091//1 1133//1 1092//1
+f 1133//1 1134//1 1092//1
+f 1092//1 1134//1 1093//1
+f 1134//1 1135//1 1093//1
+f 1093//1 1135//1 1094//1
+f 1135//1 1136//1 1094//1
+f 1094//1 1136//1 1095//1
+f 1136//1 1137//1 1095//1
+f 1095//1 1137//1 1096//1
+f 1137//1 1138//1 1096//1
+f 1096//1 1138//1 1097//1
+f 1138//1 1139//1 1097//1
+f 1097//1 1139//1 1098//1
+f 1139//1 1140//1 1098//1
+f 1098//1 1140//1 1099//1
+f 1140//1 1141//1 1099//1
+f 1099//1 1141//1 1100//1
+f 1141//1 1142//1 1100//1
+f 1100//1 1142//1 1101//1
+f 1142//1 1143//1 1101//1
+f 1101//1 1143//1 1102//1
+f 1143//1 1144//1 1102//1
+f 1102//1 1144//1 1103//1
+f 1144//1 1145//1 1103//1
+f 1103//1 1145//1 1104//1
+f 1145//1 1146//1 1104//1
+f 1104//1 1146//1 1105//1
+f 1146//1 1147//1 1105//1
+f 1105//1 1147//1 1106//1
+f 1147//1 1148//1 1106//1
+f 1106//1 1148//1 1107//1
+f 1148//1 1149//1 1107//1
+f 1107//1 1149//1 1108//1
+f 1149//1 1150//1 1108//1
+f 1108//1 1150//1 1109//1
+f 1150//1 1151//1 1109//1
+f 1109//1 1151//1 1110//1
+f 1151//1 1152//1 1110//1
+f 1110//1 1152//1 1111//1
+f 1152//1 1153//1 1111//1
+f 1111//1 1153//1 1112//1
+f 1153//1 1154//1 1112//1
+f 1112//1 1154//1 1113//1
+f 1154//1 1155//1 1113//1
+f 1113//1 1155//1 1114//1
+f 1155//1 1156//1 1114//1
+f 1114//1 1156//1 1115//1
+f 1156//1 1157//1 1115//1
+f 1115//1 1157//1 163//1
+f 1157//1 162//1 163//1
+f 247//1 1158//1 1116//1
+f 1158//1 1159//1 1116//1
+f 1116//1 1159//1 1117//1
+f 1159//1 1160//1 1117//1
+f 1117//1 1160//1 1118//1
+f 1160//1 1161//1 1118//1
+f 1118//1 1161//1 1119//1
+f 1161//1 1162//1 1119//1
+f 1119//1 1162//1 1120//1
+f 1162//1 1163//1 1120//1
+f 1120//1 1163//1 1121//1
+f 1163//1 1164//1 1121//1
+f 1121//1 1164//1 1122//1
+f 1164//1 1165//1 1122//1
+f 1122//1 1165//1 1123//1
+f 1165//1 1166//1 1123//1
+f 1123//1 1166//1 1124//1
+f 1166//1 1167//1 1124//1
+f 1124//1 1167//1 1125//1
+f 1167//1 1168//1 1125//1
+f 1125//1 1168//1 1126//1
+f 1168//1 1169//1 1126//1
+f 1126//1 1169//1 1127//1
+f 1169//1 1170//1 1127//1
+f 1127//1 1170//1 1128//1
+f 1170//1 1171//1 1128//1
+f 1128//1 1171//1 1129//1
+f 1171//1 1172//1 1129//1
+f 1129//1 1172//1 1130//1
+f 1172//1 1173//1 1130//1
+f 1130//1 1173//1 1131//1
+f 1173//1 1174//1 1131//1
+f 1131//1 1174//1 1132//1
+f 1174//1 1175//1 1132//1
+f 1132//1 1175//1 1133//1
+f 1175//1 1176//1 1133//1
+f 1133//1 1176//1 1134//1
+f 1176//1 1177//1 1134//1
+f 1134//1 1177//1 1135//1
+f 1177//1 1178//1 1135//1
+f 1135//1 1178//1 1136//1
+f 1178//1 1179//1 1136//1
+f 1136//1 1179//1 1137//1
+f 1179//1 1180//1 1137//1
+f 1137//1 1180//1 1138//1
+f 1180//1 1181//1 1138//1
+f 1138//1 1181//1 1139//1
+f 1181//1 1182//1 1139//1
+f 1139//1 1182//1 1140//1
+f 1182//1 1183//1 1140//1
+f 1140//1 1183//1 1141//1
+f 1183//1 1184//1 1141//1
+f 1141//1 1184//1 1142//1
+f 1184//1 1185//1 1142//1
+f 1142//1 1185//1 1143//1
+f 1185//1 1186//1 1143//1
+f 1143//1 1186//1 1144//1
+f 1186//1 1187//1 1144//1
+f 1144//1 1187//1 1145//1
+f 1187//1 1188//1 1145//1
+f 1145//1 1188//1 1146//1
+f 1188//1 1189//1 1146//1
+f 1146//1 1189//1 1147//1
+f 1189//1 1190//1 1147//1
+f 1147//1 1190//1 1148//1
+f 1190//1 1191//1 1148//1
+f 1148//1 1191//1 1149//1
+f 1191//1 1192//1 1149//1
+f 1149//1 1192//1 1150//1
+f 1192//1 1193//1 1150//1
+f 1150//1 1193//1 1151//1
+f 1193//1 1194//1 1151//1
+f 1151//1 1194//1 1152//1
+f 1194//1 1195//1 1152//1
+f 1152//1 1195//1 1153//1
+f 1195//1 1196//1 1153//1
+f 1153//1 1196//1 1154//1
+f 1196//1 1197//1 1154//1
+f 1154//1 1197//1 1155//1
+f 1197//1 1198//1 1155//1
+f 1155//1 1198//1 1156//1
+f 1198//1 1199//1 1156//1
+f 1156//1 1199//1 1157//1
+f 1199//1 1200//1 1157//1
+f 1157//1 1200//1 162//1
+f 1200//1 161//1 162//1
+f 248//1 1201//1 1158//1
+f 1201//1 1202//1 1158//1
+f 1158//1 1202//1 1159//1
+f 1202//1 1203//1 1159//1
+f 1159//1 1203//1 1160//1
+f 1203//1 1204//1 1160//1
+f 1160//1 1204//1 1161//1
+f 1204//1 1205//1 1161//1
+f 1161//1 1205//1 1162//1
+f 1205//1 1206//1 1162//1
+f 1162//1 1206//1 1163//1
+f 1206//1 1207//1 1163//1
+f 1163//1 1207//1 1164//1
+f 1207//1 1208//1 1164//1
+f 1164//1 1208//1 1165//1
+f 1208//1 1209//1 1165//1
+f 1165//1 1209//1 1166//1
+f 1209//1 1210//1 1166//1
+f 1166//1 1210//1 1167//1
+f 1210//1 1211//1 1167//1
+f 1167//1 1211//1 1168//1
+f 1211//1 1212//1 1168//1
+f 1168//1 1212//1 1169//1
+f 1212//1 1213//1 1169//1
+f 1169//1 1213//1 1170//1
+f 1213//1 1214//1 1170//1
+f 1170//1 1214//1 1171//1
+f 1214//1 1215//1 1171//1
+f 1171//1 1215//1 1172//1
+f 1215//1 1216//1 1172//1
+f 1172//1 1216//1 1173//1
+f 1216//1 1217//1 1173//1
+f 1173//1 1217//1 1174//1
+f 1217//1 1218//1 1174//1
+f 1174//1 1218//1 1175//1
+f 1218//1 1219//1 1175//1
+f 1175//1 1219//1 1176//1
+f 1219//1 1220//1 1176//1
+f 1176//1 1220//1 1177//1
+f 1220//1 1221//1 1177//1
+f 1177//1 1221//1 1178//1
+f 1221//1 1222//1 1178//1
+f 1178//1 1222//1 1179//1
+f 1222//1 1223//1 1179//1
+f 1179//1 1223//1 1180//1
+f 1223//1 1224//1 1180//1
+f 1180//1 1224//1 1181//1
+f 1224//1 1225//1 1181//1
+f 1181//1 1225//1 1182//1
+f 1225//1 1226//1 1182//1
+f 1182//1 1226//1 1183//1
+f 1226//1 1227//1 1183//1
+f 1183//1 1227//1 1184//1
+f 1227//1 1228//1 1184//1
+f 1184//1 1228//1 1185//1
+f 1228//1 1229//1 1185//1
+f 1185//1 1229//1 1186//1
+f 1229//1 1230//1 1186//1
+f 1186//1 1230//1 1187//1
+f 1230//1 1231//1 1187//1
+f 1187//1 1231//1 1188//1
+f 1231//1 1232//1 1188//1
+f 1188//1 1232//1 1189//1
+f 1232//1 1233//1 1189//1
+f 1189//1 1233//1 1190//1
+f 1233//1 1234//1 1190//1
+f 1190//1 1234//1 1191//1
+f 1234//1 1235//1 1191//1
+f 1191//1 1235//1 1192//1
+f 1235//1 1236//1 1192//1
+f 1192//1 1236//1 1193//1
+f 1236//1 1237//1 1193//1
+f 1193//1 1237//1 1194//1
+f 1237//1 1238//1 1194//1
+f 1194//1 1238//1 1195//1
+f 1238//1 1239//1 1195//1
+f 1195//1 1239//1 1196//1
+f 1239//1 1240//1 1196//1
+f 1196//1 1240//1 1197//1
+f 1240//1 1241//1 1197//1
+f 1197//1 1241//1 1198//1
+f 1241//1 1242//1 1198//1
+f 1198//1 1242//1 1199//1
+f 1242//1 1243//1 1199//1
+f 1199//1 1243//1 1200//1
+f 1243//1 1244//1 1200//1
+f 1200//1 1244//1 161//1
+f 1244//1 160//1 161//1
+f 249//1 1245//1 1201//1
+f 1245//1 1246//1 1201//1
+f 1201//1 1246//1 1202//1
+f 1246//1 1247//1 1202//1
+f 1202//1 1247//1 1203//1
+f 1247//1 1248//1 1203//1
+f 1203//1 1248//1 1204//1
+f 1248//1 1249//1 1204//1
+f 1204//1 1249//1 1205//1
+f 1249//1 1250//1 1205//1
+f 1205//1 1250//1 1206//1
+f 1250//1 1251//1 1206//1
+f 1206//1 1251//1 1207//1
+f 1251//1 1252//1 1207//1
+f 1207//1 1252//1 1208//1
+f 1252//1 1253//1 1208//1
+f 1208//1 1253//1 1209//1
+f 1253//1 1254//1 1209//1
+f 1209//1 1254//1 1210//1
+f 1254//1 1255//1 1210//1
+f 1210//1 1255//1 1211//1
+f 1255//1 1256//1 1211//1
+f 1211//1 1256//1 1212//1
+f 1256//1 1257//1 1212//1
+f 1212//1 1257//1 1213//1
+f 1257//1 1258//1 1213//1
+f 1213//1 1258//1 1214//1
+f 1258//1 1259//1 1214//1
+f 1214//1 1259//1 1215//1
+f 1259//1 1260//1 1215//1
+f 1215//1 1260//1 1216//1
+f 1260//1 1261//1 1216//1
+f 1216//1 1261//1 1217//1
+f 1261//1 1262//1 1217//1
+f 1217//1 1262//1 1218//1
+f 1262//1 1263//1 1218//1
+f 1218//1 1263//1 1219//1
+f 1263//1 1264//1 1219//1
+f 1219//1 1264//1 1220//1
+f 1264//1 1265//1 1220//1
+f 1220//1 1265//1 1221//1
+f 1265//1 1266//1 1221//1
+f 1221//1 1266//1 1222//1
+f 1266//1 1267//1 1222//1
+f 1222//1 1267//1 1223//1
+f 1267//1 1268//1 1223//1
+f 1223//1 1268//1 1224//1
+f 1268//1 1269//1 1224//1
+f 1224//1 1269//1 1225//1
+f 1269//1 1270//1 1225//1
+f 1225//1 1270//1 1226//1
+f 1270//1 1271//1 1226//1
+f 1226//1 1271//1 1227//1
+f 1271//1 1272//1 1227//1
+f 1227//1 1272//1 1228//1
+f 1272//1 1273//1 1228//1
+f 1228//1 1273//1 1229//1
+f 1273//1 1274//1 1229//1
+f 1229//1 1274//1 1230//1
+f 1274//1 1275//1 1230//1
+f 1230//1 1275//1 1231//1
+f 1275//1 1276//1 1231//1
+f 1231//1 1276//1 1232//1
+f 1276//1 1277//1 1232//1
+f 1232//1 1277//1 1233//1
+f 1277//1 1278//1 1233//1
+f 1233//1 1278//1 1234//1
+f 1278//1 1279//1 1234//1
+f 1234//1 1279//1 1235//1
+f 1279//1 1280//1 1235//1
+f 1235//1 1280//1 1236//1
+f 1280//1 1281//1 1236//1
+f 1236//1 1281//1 1237//1
+f 1281//1 1282//1 1237//1
+f 1237//1 1282//1 1238//1
+f 1282//1 1283//1 1238//1
+f 1238//1 1283//1 1239//1
+f 1283//1 1284//1 1239//1
+f 1239//1 1284//1 1240//1
+f 1284//1 1285//1 1240//1
+f 1240//1 1285//1 1241//1
+f 1285//1 1286//1 1241//1
+f 1241//1 1286//1 1242//1
+f 1286//1 1287//1 1242//1
+f 1242//1 1287//1 1243//1
+f 1287//1 1288//1 1243//1
+f 1243//1 1288//1 1244//1
+f 1288//1 1289//1 1244//1
+f 1244//1 1289//1 160//1
+f 1289//1 159//1 160//1
+f 250//1 1290//1 1245//1
+f 1290//1 1291//1 1245//1
+f 1245//1 1291//1 1246//1
+f 1291//1 1292//1 1246//1
+f 1246//1 1292//1 1247//1
+f 1292//1 1293//1 1247//1
+f 1247//1 1293//1 1248//1
+f 1293//1 1294//1 1248//1
+f 1248//1 1294//1 1249//1
+f 1294//1 1295//1 1249//1
+f 1249//1 1295//1 1250//1
+f 1295//1 1296//1 1250//1
+f 1250//1 1296//1 1251//1
+f 1296//1 1297//1 1251//1
+f 1251//1 1297//1 1252//1
+f 1297//1 1298//1 1252//1
+f 1252//1 1298//1 1253//1
+f 1298//1 1299//1 1253//1
+f 1253//1 1299//1 1254//1
+f 1299//1 1300//1 1254//1
+f 1254//1 1300//1 1255//1
+f 1300//1 1301//1 1255//1
+f 1255//1 1301//1 1256//1
+f 1301//1 1302//1 1256//1
+f 1256//1 1302//1 1257//1
+f 1302//1 1303//1 1257//1
+f 1257//1 1303//1 1258//1
+f 1303//1 1304//1 1258//1
+f 1258//1 1304//1 1259//1
+f 1304//1 1305//1 1259//1
+f 1259//1 1305//1 1260//1
+f 1305//1 1306//1 1260//1
+f 1260//1 1306//1 1261//1
+f 1306//1 1307//1 1261//1
+f 1261//1 1307//1 1262//1
+f 1307//1 1308//1 1262//1
+f 1262//1 1308//1 1263//1
+f 1308//1 1309//1 1263//1
+f 1263//1 1309//1 1264//1
+f 1309//1 1310//1 1264//1
+f 1264//1 1310//1 1265//1
+f 1310//1 1311//1 1265//1
+f 1265//1 1311//1 1266//1
+f 1311//1 1312//1 1266//1
+f 1266//1 1312//1 1267//1
+f 1312//1 1313//1 1267//1
+f 1267//1 1313//1 1268//1
+f 1313//1 1314//1 1268//1
+f 1268//1 1314//1 1269//1
+f 1314//1 1315//1 1269//1
+f 1269//1 1315//1 1270//1
+f 1315//1 1316//1 1270//1
+f 1270//1 1316//1 1271//1
+f 1316//1 1317//1 1271//1
+f 1271//1 1317//1 1272//1
+f 1317//1 1318//1 1272//1
+f 1272//1 1318//1 1273//1
+f 1318//1 1319//1 1273//1
+f 1273//1 1319//1 1274//1
+f 1319//1 1320//1 1274//1
+f 1274//1 1320//1 1275//1
+f 1320//1 1321//1 1275//1
+f 1275//1 1321//1 1276//1
+f 1321//1 1322//1 1276//1
+f 1276//1 1322//1 1277//1
+f 1322//1 1323//1 1277//1
+f 1277//1 1323//1 1278//1
+f 1323//1 1324//1 1278//1
+f 1278//1 1324//1 1279//1
+f 1324//1 1325//1 1279//1
+f 1279//1 1325//1 1280//1
+f 1325//1 1326//1 1280//1
+f 1280//1 1326//1 1281//1
+f 1326//1 1327//1 1281//1
+f 1281//1 1327//1 1282//1
+f 1327//1 1328//1 1282//1
+f 1282//1 1328//1 1283//1
+f 1328//1 1329//1 1283//1
+f 1283//1 1329//1 1284//1
+f 1329//1 1330//1 1284//1
+f 1284//1 1330//1 1285//1
+f 1330//1 1331//1 1285//1
+f 1285//1 1331//1 1286//1
+f 1331//1 1332//1 1286//1
+f 1286//1 1332//1 1287//1
+f 1332//1 1333//1 1287//1
+f 1287//1 1333//1 1288//1
+f 1333//1 1334//1 1288//1
+f 1288//1 1334//1 1289//1
+f 1334//1 1335//1 1289//1
+f 1289//1 1335//1 159//1
+f 1335//1 158//1 159//1
+f 251//1 1336//1 1290//1
+f 1336//1 1337//1 1290//1
+f 1290//1 1337//1 1291//1
+f 1337//1 1338//1 1291//1
+f 1291//1 1338//1 1292//1
+f 1338//1 1339//1 1292//1
+f 1292//1 1339//1 1293//1
+f 1339//1 1340//1 1293//1
+f 1293//1 1340//1 1294//1
+f 1340//1 1341//1 1294//1
+f 1294//1 1341//1 1295//1
+f 1341//1 1342//1 1295//1
+f 1295//1 1342//1 1296//1
+f 1342//1 1343//1 1296//1
+f 1296//1 1343//1 1297//1
+f 1343//1 1344//1 1297//1
+f 1297//1 1344//1 1298//1
+f 1344//1 1345//1 1298//1
+f 1298//1 1345//1 1299//1
+f 1345//1 1346//1 1299//1
+f 1299//1 1346//1 1300//1
+f 1346//1 1347//1 1300//1
+f 1300//1 1347//1 1301//1
+f 1347//1 1348//1 1301//1
+f 1301//1 1348//1 1302//1
+f 1348//1 1349//1 1302//1
+f 1302//1 1349//1 1303//1
+f 1349//1 1350//1 1303//1
+f 1303//1 1350//1 1304//1
+f 1350//1 1351//1 1304//1
+f 1304//1 1351//1 1305//1
+f 1351//1 1352//1 1305//1
+f 1305//1 1352//1 1306//1
+f 1352//1 1353//1 1306//1
+f 1306//1 1353//1 1307//1
+f 1353//1 1354//1 1307//1
+f 1307//1 1354//1 1308//1
+f 1354//1 1355//1 1308//1
+f 1308//1 1355//1 1309//1
+f 1355//1 1356//1 1309//1
+f 1309//1 1356//1 1310//1
+f 1356//1 1357//1 1310//1
+f 1310//1 1357//1 1311//1
+f 1357//1 1358//1 1311//1
+f 1311//1 1358//1 1312//1
+f 1358//1 1359//1 1312//1
+f 1312//1 1359//1 1313//1
+f 1359//1 1360//1 1313//1
+f 1313//1 1360//1 1314//1
+f 1360//1 1361//1 1314//1
+f 1314//1 1361//1 1315//1
+f 1361//1 1362//1 1315//1
+f 1315//1 1362//1 1316//1
+f 1362//1 1363//1 1316//1
+f 1316//1 1363//1 1317//1
+f 1363//1 1364//1 1317//1
+f 1317//1 1364//1 1318//1
+f 1364//1 1365//1 1318//1
+f 1318//1 1365//1 1319//1
+f 1365//1 1366//1 1319//1
+f 1319//1 1366//1 1320//1
+f 1366//1 1367//1 1320//1
+f 1320//1 1367//1 1321//1
+f 1367//1 1368//1 1321//1
+f 1321//1 1368//1 1322//1
+f 1368//1 1369//1 1322//1
+f 1322//1 1369//1 1323//1
+f 1369//1 1370//1 1323//1
+f 1323//1 1370//1 1324//1
+f 1370//1 1371//1 1324//1
+f 1324//1 1371//1 1325//1
+f 1371//1 1372//1 1325//1
+f 1325//1 1372//1 1326//1
+f 1372//1 1373//1 1326//1
+f 1326//1 1373//1 1327//1
+f 1373//1 1374//1 1327//1
+f 1327//1 1374//1 1328//1
+f 1374//1 1375//1 1328//1
+f 1328//1 1375//1 1329//1
+f 1375//1 1376//1 1329//1
+f 1329//1 1376//1 1330//1
+f 1376//1 1377//1 1330//1
+f 1330//1 1377//1 1331//1
+f 1377//1 1378//1 1331//1
+f 1331//1 1378//1 1332//1
+f 1378//1 1379//1 1332//1
+f 1332//1 1379//1 1333//1
+f 1379//1 1380//1 1333//1
+f 1333//1 1380//1 1334//1
+f 1380//1 1381//1 1334//1
+f 1334//1 1381//1 1335//1
+f 1381//1 1382//1 1335//1
+f 1335//1 1382//1 158//1
+f 1382//1 157//1 158//1
+f 252//1 1383//1 1336//1
+f 1383//1 1384//1 1336//1
+f 1336//1 1384//1 1337//1
+f 1384//1 1385//1 1337//1
+f 1337//1 1385//1 1338//1
+f 1385//1 1386//1 1338//1
+f 1338//1 1386//1 1339//1
+f 1386//1 1387//1 1339//1
+f 1339//1 1387//1 1340//1
+f 1387//1 1388//1 1340//1
+f 1340//1 1388//1 1341//1
+f 1388//1 1389//1 1341//1
+f 1341//1 1389//1 1342//1
+f 1389//1 1390//1 1342//1
+f 1342//1 1390//1 1343//1
+f 1390//1 1391//1 1343//1
+f 1343//1 1391//1 1344//1
+f 1391//1 1392//1 1344//1
+f 1344//1 1392//1 1345//1
+f 1392//1 1393//1 1345//1
+f 1345//1 1393//1 1346//1
+f 1393//1 1394//1 1346//1
+f 1346//1 1394//1 1347//1
+f 1394//1 1395//1 1347//1
+f 1347//1 1395//1 1348//1
+f 1395//1 1396//1 1348//1
+f 1348//1 1396//1 1349//1
+f 1396//1 1397//1 1349//1
+f 1349//1 1397//1 1350//1
+f 1397//1 1398//1 1350//1
+f 1350//1 1398//1 1351//1
+f 1398//1 1399//1 1351//1
+f 1351//1 1399//1 1352//1
+f 1399//1 1400//1 1352//1
+f 1352//1 1400//1 1353//1
+f 1400//1 1401//1 1353//1
+f 1353//1 1401//1 1354//1
+f 1401//1 1402//1 1354//1
+f 1354//1 1402//1 1355//1
+f 1402//1 1403//1 1355//1
+f 1355//1 1403//1 1356//1
+f 1403//1 1404//1 1356//1
+f 1356//1 1404//1 1357//1
+f 1404//1 1405//1 1357//1
+f 1357//1 1405//1 1358//1
+f 1405//1 1406//1 1358//1
+f 1358//1 1406//1 1359//1
+f 1406//1 1407//1 1359//1
+f 1359//1 1407//1 1360//1
+f 1407//1 1408//1 1360//1
+f 1360//1 1408//1 1361//1
+f 1408//1 1409//1 1361//1
+f 1361//1 1409//1 1362//1
+f 1409//1 1410//1 1362//1
+f 1362//1 1410//1 1363//1
+f 1410//1 1411//1 1363//1
+f 1363//1 1411//1 1364//1
+f 1411//1 1412//1 1364//1
+f 1364//1 1412//1 1365//1
+f 1412//1 1413//1 1365//1
+f 1365//1 1413//1 1366//1
+f 1413//1 1414//1 1366//1
+f 1366//1 1414//1 1367//1
+f 1414//1 1415//1 1367//1
+f 1367//1 1415//1 1368//1
+f 1415//1 1416//1 1368//1
+f 1368//1 1416//1 1369//1
+f 1416//1 1417//1 1369//1
+f 1369//1 1417//1 1370//1
+f 1417//1 1418//1 1370//1
+f 1370//1 1418//1 1371//1
+f 1418//1 1419//1 1371//1
+f 1371//1 1419//1 1372//1
+f 1419//1 1420//1 1372//1
+f 1372//1 1420//1 1373//1
+f 1420//1 1421//1 1373//1
+f 1373//1 1421//1 1374//1
+f 1421//1 1422//1 1374//1
+f 1374//1 1422//1 1375//1
+f 1422//1 1423//1 1375//1
+f 1375//1 1423//1 1376//1
+f 1423//1 1424//1 1376//1
+f 1376//1 1424//1 1377//1
+f 1424//1 1425//1 1377//1
+f 1377//1 1425//1 1378//1
+f 1425//1 1426//1 1378//1
+f 1378//1 1426//1 1379//1
+f 1426//1 1427//1 1379//1
+f 1379//1 1427//1 1380//1
+f 1427//1 1428//1 1380//1
+f 1380//1 1428//1 1381//1
+f 1428//1 1429//1 1381//1
+f 1381//1 1429//1 1382//1
+f 1429//1 1430//1 1382//1
+f 1382//1 1430//1 157//1
+f 1430//1 156//1 157//1
+f 253//1 1431//1 1383//1
+f 1431//1 1432//1 1383//1
+f 1383//1 1432//1 1384//1
+f 1432//1 1433//1 1384//1
+f 1384//1 1433//1 1385//1
+f 1433//1 1434//1 1385//1
+f 1385//1 1434//1 1386//1
+f 1434//1 1435//1 1386//1
+f 1386//1 1435//1 1387//1
+f 1435//1 1436//1 1387//1
+f 1387//1 1436//1 1388//1
+f 1436//1 1437//1 1388//1
+f 1388//1 1437//1 1389//1
+f 1437//1 1438//1 1389//1
+f 1389//1 1438//1 1390//1
+f 1438//1 1439//1 1390//1
+f 1390//1 1439//1 1391//1
+f 1439//1 1440//1 1391//1
+f 1391//1 1440//1 1392//1
+f 1440//1 1441//1 1392//1
+f 1392//1 1441//1 1393//1
+f 1441//1 1442//1 1393//1
+f 1393//1 1442//1 1394//1
+f 1442//1 1443//1 1394//1
+f 1394//1 1443//1 1395//1
+f 1443//1 1444//1 1395//1
+f 1395//1 1444//1 1396//1
+f 1444//1 1445//1 1396//1
+f 1396//1 1445//1 1397//1
+f 1445//1 1446//1 1397//1
+f 1397//1 1446//1 1398//1
+f 1446//1 1447//1 1398//1
+f 1398//1 1447//1 1399//1
+f 1447//1 1448//1 1399//1
+f 1399//1 1448//1 1400//1
+f 1448//1 1449//1 1400//1
+f 1400//1 1449//1 1401//1
+f 1449//1 1450//1 1401//1
+f 1401//1 1450//1 1402//1
+f 1450//1 1451//1 1402//1
+f 1402//1 1451//1 1403//1
+f 1451//1 1452//1 1403//1
+f 1403//1 1452//1 1404//1
+f 1452//1 1453//1 1404//1
+f 1404//1 1453//1 1405//1
+f 1453//1 1454//1 1405//1
+f 1405//1 1454//1 1406//1
+f 1454//1 1455//1 1406//1
+f 1406//1 1455//1 1407//1
+f 1455//1 1456//1 1407//1
+f 1407//1 1456//1 1408//1
+f 1456//1 1457//1 1408//1
+f 1408//1 1457//1 1409//1
+f 1457//1 1458//1 1409//1
+f 1409//1 1458//1 1410//1
+f 1458//1 1459//1 1410//1
+f 1410//1 1459//1 1411//1
+f 1459//1 1460//1 1411//1
+f 1411//1 1460//1 1412//1
+f 1460//1 1461//1 1412//1
+f 1412//1 1461//1 1413//1
+f 1461//1 1462//1 1413//1
+f 1413//1 1462//1 1414//1
+f 1462//1 1463//1 1414//1
+f 1414//1 1463//1 1415//1
+f 1463//1 1464//1 1415//1
+f 1415//1 1464//1 1416//1
+f 1464//1 1465//1 1416//1
+f 1416//1 1465//1 1417//1
+f 1465//1 1466//1 1417//1
+f 1417//1 1466//1 1418//1
+f 1466//1 1467//1 1418//1
+f 1418//1 1467//1 1419//1
+f 1467//1 1468//1 1419//1
+f 1419//1 1468//1 1420//1
+f 1468//1 1469//1 1420//1
+f 1420//1 1469//1 1421//1
+f 1469//1 1470//1 1421//1
+f 1421//1 1470//1 1422//1
+f 1470//1 1471//1 1422//1
+f 1422//1 1471//1 1423//1
+f 1471//1 1472//1 1423//1
+f 1423//1 1472//1 1424//1
+f 1472//1 1473//1 1424//1
+f 1424//1 1473//1 1425//1
+f 1473//1 1474//1 1425//1
+f 1425//1 1474//1 1426//1
+f 1474//1 1475//1 1426//1
+f 1426//1 1475//1 1427//1
+f 1475//1 1476//1 1427//1
+f 1427//1 1476//1 1428//1
+f 1476//1 1477//1 1428//1
+f 1428//1 1477//1 1429//1
+f 1477//1 1478//1 1429//1
+f 1429//1 1478//1 1430//1
+f 1478//1 1479//1 1430//1
+f 1430//1 1479//1 156//1
+f 1479//1 155//1 156//1
+f 254//1 105//1 1431//1
+f 105//1 106//1 1431//1
+f 1431//1 106//1 1432//1
+f 106//1 107//1 1432//1
+f 1432//1 107//1 1433//1
+f 107//1 108//1 1433//1
+f 1433//1 108//1 1434//1
+f 108//1 109//1 1434//1
+f 1434//1 109//1 1435//1
+f 109//1 110//1 1435//1
+f 1435//1 110//1 1436//1
+f 110//1 111//1 1436//1
+f 1436//1 111//1 1437//1
+f 111//1 112//1 1437//1
+f 1437//1 112//1 1438//1
+f 112//1 113//1 1438//1
+f 1438//1 113//1 1439//1
+f 113//1 114//1 1439//1
+f 1439//1 114//1 1440//1
+f 114//1 115//1 1440//1
+f 1440//1 115//1 1441//1
+f 115//1 116//1 1441//1
+f 1441//1 116//1 1442//1
+f 116//1 117//1 1442//1
+f 1442//1 117//1 1443//1
+f 117//1 118//1 1443//1
+f 1443//1 118//1 1444//1
+f 118//1 119//1 1444//1
+f 1444//1 119//1 1445//1
+f 119//1 120//1 1445//1
+f 1445//1 120//1 1446//1
+f 120//1 121//1 1446//1
+f 1446//1 121//1 1447//1
+f 121//1 122//1 1447//1
+f 1447//1 122//1 1448//1
+f 122//1 123//1 1448//1
+f 1448//1 123//1 1449//1
+f 123//1 124//1 1449//1
+f 1449//1 124//1 1450//1
+f 124//1 125//1 1450//1
+f 1450//1 125//1 1451//1
+f 125//1 126//1 1451//1
+f 1451//1 126//1 1452//1
+f 126//1 127//1 1452//1
+f 1452//1 127//1 1453//1
+f 127//1 128//1 1453//1
+f 1453//1 128//1 1454//1
+f 128//1 129//1 1454//1
+f 1454//1 129//1 1455//1
+f 129//1 130//1 1455//1
+f 1455//1 130//1 1456//1
+f 130//1 131//1 1456//1
+f 1456//1 131//1 1457//1
+f 131//1 132//1 1457//1
+f 1457//1 132//1 1458//1
+f 132//1 133//1 1458//1
+f 1458//1 133//1 1459//1
+f 133//1 134//1 1459//1
+f 1459//1 134//1 1460//1
+f 134//1 135//1 1460//1
+f 1460//1 135//1 1461//1
+f 135//1 136//1 1461//1
+f 1461//1 136//1 1462//1
+f 136//1 137//1 1462//1
+f 1462//1 137//1 1463//1
+f 137//1 138//1 1463//1
+f 1463//1 138//1 1464//1
+f 138//1 139//1 1464//1
+f 1464//1 139//1 1465//1
+f 139//1 140//1 1465//1
+f 1465//1 140//1 1466//1
+f 140//1 141//1 1466//1
+f 1466//1 141//1 1467//1
+f 141//1 142//1 1467//1
+f 1467//1 142//1 1468//1
+f 142//1 143//1 1468//1
+f 1468//1 143//1 1469//1
+f 143//1 144//1 1469//1
+f 1469//1 144//1 1470//1
+f 144//1 145//1 1470//1
+f 1470//1 145//1 1471//1
+f 145//1 146//1 1471//1
+f 1471//1 146//1 1472//1
+f 146//1 147//1 1472//1
+f 1472//1 147//1 1473//1
+f 147//1 148//1 1473//1
+f 1473//1 148//1 1474//1
+f 148//1 149//1 1474//1
+f 1474//1 149//1 1475//1
+f 149//1 150//1 1475//1
+f 1475//1 150//1 1476//1
+f 150//1 151//1 1476//1
+f 1476//1 151//1 1477//1
+f 151//1 152//1 1477//1
+f 1477//1 152//1 1478//1
+f 152//1 153//1 1478//1
+f 1478//1 153//1 1479//1
+f 153//1 154//1 1479//1
+f 1479//1 154//1 155//1
+f 154//1 4//1 155//1
+f 55//1 54//1 1//1
+f 56//1 1480//1 55//1
+f 57//1 1481//1 56//1
+f 58//1 1483//1 57//1
+f 59//1 1486//1 58//1
+f 60//1 1490//1 59//1
+f 61//1 1495//1 60//1
+f 62//1 1501//1 61//1
+f 63//1 1508//1 62//1
+f 64//1 1516//1 63//1
+f 65//1 1525//1 64//1
+f 66//1 1535//1 65//1
+f 67//1 1546//1 66//1
+f 68//1 1558//1 67//1
+f 69//1 1571//1 68//1
+f 70//1 1585//1 69//1
+f 71//1 1600//1 70//1
+f 72//1 1616//1 71//1
+f 73//1 1633//1 72//1
+f 74//1 1651//1 73//1
+f 75//1 1670//1 74//1
+f 76//1 1690//1 75//1
+f 77//1 1711//1 76//1
+f 78//1 1733//1 77//1
+f 79//1 1756//1 78//1
+f 80//1 1780//1 79//1
+f 81//1 1805//1 80//1
+f 82//1 1831//1 81//1
+f 83//1 1858//1 82//1
+f 84//1 1886//1 83//1
+f 85//1 1915//1 84//1
+f 86//1 1945//1 85//1
+f 87//1 1976//1 86//1
+f 88//1 2008//1 87//1
+f 89//1 2041//1 88//1
+f 90//1 2075//1 89//1
+f 91//1 2110//1 90//1
+f 92//1 2146//1 91//1
+f 93//1 2183//1 92//1
+f 94//1 2221//1 93//1
+f 95//1 2260//1 94//1
+f 96//1 2300//1 95//1
+f 97//1 2341//1 96//1
+f 98//1 2383//1 97//1
+f 99//1 2426//1 98//1
+f 100//1 2470//1 99//1
+f 101//1 2515//1 100//1
+f 102//1 2561//1 101//1
+f 103//1 2608//1 102//1
+f 104//1 2656//1 103//1
+f 55//1 1480//1 54//1
+f 1480//1 53//1 54//1
+f 56//1 1481//1 1480//1
+f 1481//1 1482//1 1480//1
+f 1480//1 1482//1 53//1
+f 1482//1 52//1 53//1
+f 57//1 1483//1 1481//1
+f 1483//1 1484//1 1481//1
+f 1481//1 1484//1 1482//1
+f 1484//1 1485//1 1482//1
+f 1482//1 1485//1 52//1
+f 1485//1 51//1 52//1
+f 58//1 1486//1 1483//1
+f 1486//1 1487//1 1483//1
+f 1483//1 1487//1 1484//1
+f 1487//1 1488//1 1484//1
+f 1484//1 1488//1 1485//1
+f 1488//1 1489//1 1485//1
+f 1485//1 1489//1 51//1
+f 1489//1 50//1 51//1
+f 59//1 1490//1 1486//1
+f 1490//1 1491//1 1486//1
+f 1486//1 1491//1 1487//1
+f 1491//1 1492//1 1487//1
+f 1487//1 1492//1 1488//1
+f 1492//1 1493//1 1488//1
+f 1488//1 1493//1 1489//1
+f 1493//1 1494//1 1489//1
+f 1489//1 1494//1 50//1
+f 1494//1 49//1 50//1
+f 60//1 1495//1 1490//1
+f 1495//1 1496//1 1490//1
+f 1490//1 1496//1 1491//1
+f 1496//1 1497//1 1491//1
+f 1491//1 1497//1 1492//1
+f 1497//1 1498//1 1492//1
+f 1492//1 1498//1 1493//1
+f 1498//1 1499//1 1493//1
+f 1493//1 1499//1 1494//1
+f 1499//1 1500//1 1494//1
+f 1494//1 1500//1 49//1
+f 1500//1 48//1 49//1
+f 61//1 1501//1 1495//1
+f 1501//1 1502//1 1495//1
+f 1495//1 1502//1 1496//1
+f 1502//1 1503//1 1496//1
+f 1496//1 1503//1 1497//1
+f 1503//1 1504//1 1497//1
+f 1497//1 1504//1 1498//1
+f 1504//1 1505//1 1498//1
+f 1498//1 1505//1 1499//1
+f 1505//1 1506//1 1499//1
+f 1499//1 1506//1 1500//1
+f 1506//1 1507//1 1500//1
+f 1500//1 1507//1 48//1
+f 1507//1 47//1 48//1
+f 62//1 1508//1 1501//1
+f 1508//1 1509//1 1501//1
+f 1501//1 1509//1 1502//1
+f 1509//1 1510//1 1502//1
+f 1502//1 1510//1 1503//1
+f 1510//1 1511//1 1503//1
+f 1503//1 1511//1 1504//1
+f 1511//1 1512//1 1504//1
+f 1504//1 1512//1 1505//1
+f 1512//1 1513//1 1505//1
+f 1505//1 1513//1 1506//1
+f 1513//1 1514//1 1506//1
+f 1506//1 1514//1 1507//1
+f 1514//1 1515//1 1507//1
+f 1507//1 1515//1 47//1
+f 1515//1 46//1 47//1
+f 63//1 1516//1 1508//1
+f 1516//1 1517//1 1508//1
+f 1508//1 1517//1 1509//1
+f 1517//1 1518//1 1509//1
+f 1509//1 1518//1 1510//1
+f 1518//1 1519//1 1510//1
+f 1510//1 1519//1 1511//1
+f 1519//1 1520//1 1511//1
+f 1511//1 1520//1 1512//1
+f 1520//1 1521//1 1512//1
+f 1512//1 1521//1 1513//1
+f 1521//1 1522//1 1513//1
+f 1513//1 1522//1 1514//1
+f 1522//1 1523//1 1514//1
+f 1514//1 1523//1 1515//1
+f 1523//1 1524//1 1515//1
+f 1515//1 1524//1 46//1
+f 1524//1 45//1 46//1
+f 64//1 1525//1 1516//1
+f 1525//1 1526//1 1516//1
+f 1516//1 1526//1 1517//1
+f 1526//1 1527//1 1517//1
+f 1517//1 1527//1 1518//1
+f 1527//1 1528//1 1518//1
+f 1518//1 1528//1 1519//1
+f 1528//1 1529//1 1519//1
+f 1519//1 1529//1 1520//1
+f 1529//1 1530//1 1520//1
+f 1520//1 1530//1 1521//1
+f 1530//1 1531//1 1521//1
+f 1521//1 1531//1 1522//1
+f 1531//1 1532//1 1522//1
+f 1522//1 1532//1 1523//1
+f 1532//1 1533//1 1523//1
+f 1523//1 1533//1 1524//1
+f 1533//1 1534//1 1524//1
+f 1524//1 1534//1 45//1
+f 1534//1 44//1 45//1
+f 65//1 1535//1 1525//1
+f 1535//1 1536//1 1525//1
+f 1525//1 1536//1 1526//1
+f 1536//1 1537//1 1526//1
+f 1526//1 1537//1 1527//1
+f 1537//1 1538//1 1527//1
+f 1527//1 1538//1 1528//1
+f 1538//1 1539//1 1528//1
+f 1528//1 1539//1 1529//1
+f 1539//1 1540//1 1529//1
+f 1529//1 1540//1 1530//1
+f 1540//1 1541//1 1530//1
+f 1530//1 1541//1 1531//1
+f 1541//1 1542//1 1531//1
+f 1531//1 1542//1 1532//1
+f 1542//1 1543//1 1532//1
+f 1532//1 1543//1 1533//1
+f 1543//1 1544//1 1533//1
+f 1533//1 1544//1 1534//1
+f 1544//1 1545//1 1534//1
+f 1534//1 1545//1 44//1
+f 1545//1 43//1 44//1
+f 66//1 1546//1 1535//1
+f 1546//1 1547//1 1535//1
+f 1535//1 1547//1 1536//1
+f 1547//1 1548//1 1536//1
+f 1536//1 1548//1 1537//1
+f 1548//1 1549//1 1537//1
+f 1537//1 1549//1 1538//1
+f 1549//1 1550//1 1538//1
+f 1538//1 1550//1 1539//1
+f 1550//1 1551//1 1539//1
+f 1539//1 1551//1 1540//1
+f 1551//1 1552//1 1540//1
+f 1540//1 1552//1 1541//1
+f 1552//1 1553//1 1541//1
+f 1541//1 1553//1 1542//1
+f 1553//1 1554//1 1542//1
+f 1542//1 1554//1 1543//1
+f 1554//1 1555//1 1543//1
+f 1543//1 1555//1 1544//1
+f 1555//1 1556//1 1544//1
+f 1544//1 1556//1 1545//1
+f 1556//1 1557//1 1545//1
+f 1545//1 1557//1 43//1
+f 1557//1 42//1 43//1
+f 67//1 1558//1 1546//1
+f 1558//1 1559//1 1546//1
+f 1546//1 1559//1 1547//1
+f 1559//1 1560//1 1547//1
+f 1547//1 1560//1 1548//1
+f 1560//1 1561//1 1548//1
+f 1548//1 1561//1 1549//1
+f 1561//1 1562//1 1549//1
+f 1549//1 1562//1 1550//1
+f 1562//1 1563//1 1550//1
+f 1550//1 1563//1 1551//1
+f 1563//1 1564//1 1551//1
+f 1551//1 1564//1 1552//1
+f 1564//1 1565//1 1552//1
+f 1552//1 1565//1 1553//1
+f 1565//1 1566//1 1553//1
+f 1553//1 1566//1 1554//1
+f 1566//1 1567//1 1554//1
+f 1554//1 1567//1 1555//1
+f 1567//1 1568//1 1555//1
+f 1555//1 1568//1 1556//1
+f 1568//1 1569//1 1556//1
+f 1556//1 1569//1 1557//1
+f 1569//1 1570//1 1557//1
+f 1557//1 1570//1 42//1
+f 1570//1 41//1 42//1
+f 68//1 1571//1 1558//1
+f 1571//1 1572//1 1558//1
+f 1558//1 1572//1 1559//1
+f 1572//1 1573//1 1559//1
+f 1559//1 1573//1 1560//1
+f 1573//1 1574//1 1560//1
+f 1560//1 1574//1 1561//1
+f 1574//1 1575//1 1561//1
+f 1561//1 1575//1 1562//1
+f 1575//1 1576//1 1562//1
+f 1562//1 1576//1 1563//1
+f 1576//1 1577//1 1563//1
+f 1563//1 1577//1 1564//1
+f 1577//1 1578//1 1564//1
+f 1564//1 1578//1 1565//1
+f 1578//1 1579//1 1565//1
+f 1565//1 1579//1 1566//1
+f 1579//1 1580//1 1566//1
+f 1566//1 1580//1 1567//1
+f 1580//1 1581//1 1567//1
+f 1567//1 1581//1 1568//1
+f 1581//1 1582//1 1568//1
+f 1568//1 1582//1 1569//1
+f 1582//1 1583//1 1569//1
+f 1569//1 1583//1 1570//1
+f 1583//1 1584//1 1570//1
+f 1570//1 1584//1 41//1
+f 1584//1 40//1 41//1
+f 69//1 1585//1 1571//1
+f 1585//1 1586//1 1571//1
+f 1571//1 1586//1 1572//1
+f 1586//1 1587//1 1572//1
+f 1572//1 1587//1 1573//1
+f 1587//1 1588//1 1573//1
+f 1573//1 1588//1 1574//1
+f 1588//1 1589//1 1574//1
+f 1574//1 1589//1 1575//1
+f 1589//1 1590//1 1575//1
+f 1575//1 1590//1 1576//1
+f 1590//1 1591//1 1576//1
+f 1576//1 1591//1 1577//1
+f 1591//1 1592//1 1577//1
+f 1577//1 1592//1 1578//1
+f 1592//1 1593//1 1578//1
+f 1578//1 1593//1 1579//1
+f 1593//1 1594//1 1579//1
+f 1579//1 1594//1 1580//1
+f 1594//1 1595//1 1580//1
+f 1580//1 1595//1 1581//1
+f 1595//1 1596//1 1581//1
+f 1581//1 1596//1 1582//1
+f 1596//1 1597//1 1582//1
+f 1582//1 1597//1 1583//1
+f 1597//1 1598//1 1583//1
+f 1583//1 1598//1 1584//1
+f 1598//1 1599//1 1584//1
+f 1584//1 1599//1 40//1
+f 1599//1 39//1 40//1
+f 70//1 1600//1 1585//1
+f 1600//1 1601//1 1585//1
+f 1585//1 1601//1 1586//1
+f 1601//1 1602//1 1586//1
+f 1586//1 1602//1 1587//1
+f 1602//1 1603//1 1587//1
+f 1587//1 1603//1 1588//1
+f 1603//1 1604//1 1588//1
+f 1588//1 1604//1 1589//1
+f 1604//1 1605//1 1589//1
+f 1589//1 1605//1 1590//1
+f 1605//1 1606//1 1590//1
+f 1590//1 1606//1 1591//1
+f 1606//1 1607//1 1591//1
+f 1591//1 1607//1 1592//1
+f 1607//1 1608//1 1592//1
+f 1592//1 1608//1 1593//1
+f 1608//1 1609//1 1593//1
+f 1593//1 1609//1 1594//1
+f 1609//1 1610//1 1594//1
+f 1594//1 1610//1 1595//1
+f 1610//1 1611//1 1595//1
+f 1595//1 1611//1 1596//1
+f 1611//1 1612//1 1596//1
+f 1596//1 1612//1 1597//1
+f 1612//1 1613//1 1597//1
+f 1597//1 1613//1 1598//1
+f 1613//1 1614//1 1598//1
+f 1598//1 1614//1 1599//1
+f 1614//1 1615//1 1599//1
+f 1599//1 1615//1 39//1
+f 1615//1 38//1 39//1
+f 71//1 1616//1 1600//1
+f 1616//1 1617//1 1600//1
+f 1600//1 1617//1 1601//1
+f 1617//1 1618//1 1601//1
+f 1601//1 1618//1 1602//1
+f 1618//1 1619//1 1602//1
+f 1602//1 1619//1 1603//1
+f 1619//1 1620//1 1603//1
+f 1603//1 1620//1 1604//1
+f 1620//1 1621//1 1604//1
+f 1604//1 1621//1 1605//1
+f 1621//1 1622//1 1605//1
+f 1605//1 1622//1 1606//1
+f 1622//1 1623//1 1606//1
+f 1606//1 1623//1 1607//1
+f 1623//1 1624//1 1607//1
+f 1607//1 1624//1 1608//1
+f 1624//1 1625//1 1608//1
+f 1608//1 1625//1 1609//1
+f 1625//1 1626//1 1609//1
+f 1609//1 1626//1 1610//1
+f 1626//1 1627//1 1610//1
+f 1610//1 1627//1 1611//1
+f 1627//1 1628//1 1611//1
+f 1611//1 1628//1 1612//1
+f 1628//1 1629//1 1612//1
+f 1612//1 1629//1 1613//1
+f 1629//1 1630//1 1613//1
+f 1613//1 1630//1 1614//1
+f 1630//1 1631//1 1614//1
+f 1614//1 1631//1 1615//1
+f 1631//1 1632//1 1615//1
+f 1615//1 1632//1 38//1
+f 1632//1 37//1 38//1
+f 72//1 1633//1 1616//1
+f 1633//1 1634//1 1616//1
+f 1616//1 1634//1 1617//1
+f 1634//1 1635//1 1617//1
+f 1617//1 1635//1 1618//1
+f 1635//1 1636//1 1618//1
+f 1618//1 1636//1 1619//1
+f 1636//1 1637//1 1619//1
+f 1619//1 1637//1 1620//1
+f 1637//1 1638//1 1620//1
+f 1620//1 1638//1 1621//1
+f 1638//1 1639//1 1621//1
+f 1621//1 1639//1 1622//1
+f 1639//1 1640//1 1622//1
+f 1622//1 1640//1 1623//1
+f 1640//1 1641//1 1623//1
+f 1623//1 1641//1 1624//1
+f 1641//1 1642//1 1624//1
+f 1624//1 1642//1 1625//1
+f 1642//1 1643//1 1625//1
+f 1625//1 1643//1 1626//1
+f 1643//1 1644//1 1626//1
+f 1626//1 1644//1 1627//1
+f 1644//1 1645//1 1627//1
+f 1627//1 1645//1 1628//1
+f 1645//1 1646//1 1628//1
+f 1628//1 1646//1 1629//1
+f 1646//1 1647//1 1629//1
+f 1629//1 1647//1 1630//1
+f 1647//1 1648//1 1630//1
+f 1630//1 1648//1 1631//1
+f 1648//1 1649//1 1631//1
+f 1631//1 1649//1 1632//1
+f 1649//1 1650//1 1632//1
+f 1632//1 1650//1 37//1
+f 1650//1 36//1 37//1
+f 73//1 1651//1 1633//1
+f 1651//1 1652//1 1633//1
+f 1633//1 1652//1 1634//1
+f 1652//1 1653//1 1634//1
+f 1634//1 1653//1 1635//1
+f 1653//1 1654//1 1635//1
+f 1635//1 1654//1 1636//1
+f 1654//1 1655//1 1636//1
+f 1636//1 1655//1 1637//1
+f 1655//1 1656//1 1637//1
+f 1637//1 1656//1 1638//1
+f 1656//1 1657//1 1638//1
+f 1638//1 1657//1 1639//1
+f 1657//1 1658//1 1639//1
+f 1639//1 1658//1 1640//1
+f 1658//1 1659//1 1640//1
+f 1640//1 1659//1 1641//1
+f 1659//1 1660//1 1641//1
+f 1641//1 1660//1 1642//1
+f 1660//1 1661//1 1642//1
+f 1642//1 1661//1 1643//1
+f 1661//1 1662//1 1643//1
+f 1643//1 1662//1 1644//1
+f 1662//1 1663//1 1644//1
+f 1644//1 1663//1 1645//1
+f 1663//1 1664//1 1645//1
+f 1645//1 1664//1 1646//1
+f 1664//1 1665//1 1646//1
+f 1646//1 1665//1 1647//1
+f 1665//1 1666//1 1647//1
+f 1647//1 1666//1 1648//1
+f 1666//1 1667//1 1648//1
+f 1648//1 1667//1 1649//1
+f 1667//1 1668//1 1649//1
+f 1649//1 1668//1 1650//1
+f 1668//1 1669//1 1650//1
+f 1650//1 1669//1 36//1
+f 1669//1 35//1 36//1
+f 74//1 1670//1 1651//1
+f 1670//1 1671//1 1651//1
+f 1651//1 1671//1 1652//1
+f 1671//1 1672//1 1652//1
+f 1652//1 1672//1 1653//1
+f 1672//1 1673//1 1653//1
+f 1653//1 1673//1 1654//1
+f 1673//1 1674//1 1654//1
+f 1654//1 1674//1 1655//1
+f 1674//1 1675//1 1655//1
+f 1655//1 1675//1 1656//1
+f 1675//1 1676//1 1656//1
+f 1656//1 1676//1 1657//1
+f 1676//1 1677//1 1657//1
+f 1657//1 1677//1 1658//1
+f 1677//1 1678//1 1658//1
+f 1658//1 1678//1 1659//1
+f 1678//1 1679//1 1659//1
+f 1659//1 1679//1 1660//1
+f 1679//1 1680//1 1660//1
+f 1660//1 1680//1 1661//1
+f 1680//1 1681//1 1661//1
+f 1661//1 1681//1 1662//1
+f 1681//1 1682//1 1662//1
+f 1662//1 1682//1 1663//1
+f 1682//1 1683//1 1663//1
+f 1663//1 1683//1 1664//1
+f 1683//1 1684//1 1664//1
+f 1664//1 1684//1 1665//1
+f 1684//1 1685//1 1665//1
+f 1665//1 1685//1 1666//1
+f 1685//1 1686//1 1666//1
+f 1666//1 1686//1 1667//1
+f 1686//1 1687//1 1667//1
+f 1667//1 1687//1 1668//1
+f 1687//1 1688//1 1668//1
+f 1668//1 1688//1 1669//1
+f 1688//1 1689//1 1669//1
+f 1669//1 1689//1 35//1
+f 1689//1 34//1 35//1
+f 75//1 1690//1 1670//1
+f 1690//1 1691//1 1670//1
+f 1670//1 1691//1 1671//1
+f 1691//1 1692//1 1671//1
+f 1671//1 1692//1 1672//1
+f 1692//1 1693//1 1672//1
+f 1672//1 1693//1 1673//1
+f 1693//1 1694//1 1673//1
+f 1673//1 1694//1 1674//1
+f 1694//1 1695//1 1674//1
+f 1674//1 1695//1 1675//1
+f 1695//1 1696//1 1675//1
+f 1675//1 1696//1 1676//1
+f 1696//1 1697//1 1676//1
+f 1676//1 1697//1 1677//1
+f 1697//1 1698//1 1677//1
+f 1677//1 1698//1 1678//1
+f 1698//1 1699//1 1678//1
+f 1678//1 1699//1 1679//1
+f 1699//1 1700//1 1679//1
+f 1679//1 1700//1 1680//1
+f 1700//1 1701//1 1680//1
+f 1680//1 1701//1 1681//1
+f 1701//1 1702//1 1681//1
+f 1681//1 1702//1 1682//1
+f 1702//1 1703//1 1682//1
+f 1682//1 1703//1 1683//1
+f 1703//1 1704//1 1683//1
+f 1683//1 1704//1 1684//1
+f 1704//1 1705//1 1684//1
+f 1684//1 1705//1 1685//1
+f 1705//1 1706//1 1685//1
+f 1685//1 1706//1 1686//1
+f 1706//1 1707//1 1686//1
+f 1686//1 1707//1 1687//1
+f 1707//1 1708//1 1687//1
+f 1687//1 1708//1 1688//1
+f 1708//1 1709//1 1688//1
+f 1688//1 1709//1 1689//1
+f 1709//1 1710//1 1689//1
+f 1689//1 1710//1 34//1
+f 1710//1 33//1 34//1
+f 76//1 1711//1 1690//1
+f 1711//1 1712//1 1690//1
+f 1690//1 1712//1 1691//1
+f 1712//1 1713//1 1691//1
+f 1691//1 1713//1 1692//1
+f 1713//1 1714//1 1692//1
+f 1692//1 1714//1 1693//1
+f 1714//1 1715//1 1693//1
+f 1693//1 1715//1 1694//1
+f 1715//1 1716//1 1694//1
+f 1694//1 1716//1 1695//1
+f 1716//1 1717//1 1695//1
+f 1695//1 1717//1 1696//1
+f 1717//1 1718//1 1696//1
+f 1696//1 1718//1 1697//1
+f 1718//1 1719//1 1697//1
+f 1697//1 1719//1 1698//1
+f 1719//1 1720//1 1698//1
+f 1698//1 1720//1 1699//1
+f 1720//1 1721//1 1699//1
+f 1699//1 1721//1 1700//1
+f 1721//1 1722//1 1700//1
+f 1700//1 1722//1 1701//1
+f 1722//1 1723//1 1701//1
+f 1701//1 1723//1 1702//1
+f 1723//1 1724//1 1702//1
+f 1702//1 1724//1 1703//1
+f 1724//1 1725//1 1703//1
+f 1703//1 1725//1 1704//1
+f 1725//1 1726//1 1704//1
+f 1704//1 1726//1 1705//1
+f 1726//1 1727//1 1705//1
+f 1705//1 1727//1 1706//1
+f 1727//1 1728//1 1706//1
+f 1706//1 1728//1 1707//1
+f 1728//1 1729//1 1707//1
+f 1707//1 1729//1 1708//1
+f 1729//1 1730//1 1708//1
+f 1708//1 1730//1 1709//1
+f 1730//1 1731//1 1709//1
+f 1709//1 1731//1 1710//1
+f 1731//1 1732//1 1710//1
+f 1710//1 1732//1 33//1
+f 1732//1 32//1 33//1
+f 77//1 1733//1 1711//1
+f 1733//1 1734//1 1711//1
+f 1711//1 1734//1 1712//1
+f 1734//1 1735//1 1712//1
+f 1712//1 1735//1 1713//1
+f 1735//1 1736//1 1713//1
+f 1713//1 1736//1 1714//1
+f 1736//1 1737//1 1714//1
+f 1714//1 1737//1 1715//1
+f 1737//1 1738//1 1715//1
+f 1715//1 1738//1 1716//1
+f 1738//1 1739//1 1716//1
+f 1716//1 1739//1 1717//1
+f 1739//1 1740//1 1717//1
+f 1717//1 1740//1 1718//1
+f 1740//1 1741//1 1718//1
+f 1718//1 1741//1 1719//1
+f 1741//1 1742//1 1719//1
+f 1719//1 1742//1 1720//1
+f 1742//1 1743//1 1720//1
+f 1720//1 1743//1 1721//1
+f 1743//1 1744//1 1721//1
+f 1721//1 1744//1 1722//1
+f 1744//1 1745//1 1722//1
+f 1722//1 1745//1 1723//1
+f 1745//1 1746//1 1723//1
+f 1723//1 1746//1 1724//1
+f 1746//1 1747//1 1724//1
+f 1724//1 1747//1 1725//1
+f 1747//1 1748//1 1725//1
+f 1725//1 1748//1 1726//1
+f 1748//1 1749//1 1726//1
+f 1726//1 1749//1 1727//1
+f 1749//1 1750//1 1727//1
+f 1727//1 1750//1 1728//1
+f 1750//1 1751//1 1728//1
+f 1728//1 1751//1 1729//1
+f 1751//1 1752//1 1729//1
+f 1729//1 1752//1 1730//1
+f 1752//1 1753//1 1730//1
+f 1730//1 1753//1 1731//1
+f 1753//1 1754//1 1731//1
+f 1731//1 1754//1 1732//1
+f 1754//1 1755//1 1732//1
+f 1732//1 1755//1 32//1
+f 1755//1 31//1 32//1
+f 78//1 1756//1 1733//1
+f 1756//1 1757//1 1733//1
+f 1733//1 1757//1 1734//1
+f 1757//1 1758//1 1734//1
+f 1734//1 1758//1 1735//1
+f 1758//1 1759//1 1735//1
+f 1735//1 1759//1 1736//1
+f 1759//1 1760//1 1736//1
+f 1736//1 1760//1 1737//1
+f 1760//1 1761//1 1737//1
+f 1737//1 1761//1 1738//1
+f 1761//1 1762//1 1738//1
+f 1738//1 1762//1 1739//1
+f 1762//1 1763//1 1739//1
+f 1739//1 1763//1 1740//1
+f 1763//1 1764//1 1740//1
+f 1740//1 1764//1 1741//1
+f 1764//1 1765//1 1741//1
+f 1741//1 1765//1 1742//1
+f 1765//1 1766//1 1742//1
+f 1742//1 1766//1 1743//1
+f 1766//1 1767//1 1743//1
+f 1743//1 1767//1 1744//1
+f 1767//1 1768//1 1744//1
+f 1744//1 1768//1 1745//1
+f 1768//1 1769//1 1745//1
+f 1745//1 1769//1 1746//1
+f 1769//1 1770//1 1746//1
+f 1746//1 1770//1 1747//1
+f 1770//1 1771//1 1747//1
+f 1747//1 1771//1 1748//1
+f 1771//1 1772//1 1748//1
+f 1748//1 1772//1 1749//1
+f 1772//1 1773//1 1749//1
+f 1749//1 1773//1 1750//1
+f 1773//1 1774//1 1750//1
+f 1750//1 1774//1 1751//1
+f 1774//1 1775//1 1751//1
+f 1751//1 1775//1 1752//1
+f 1775//1 1776//1 1752//1
+f 1752//1 1776//1 1753//1
+f 1776//1 1777//1 1753//1
+f 1753//1 1777//1 1754//1
+f 1777//1 1778//1 1754//1
+f 1754//1 1778//1 1755//1
+f 1778//1 1779//1 1755//1
+f 1755//1 1779//1 31//1
+f 1779//1 30//1 31//1
+f 79//1 1780//1 1756//1
+f 1780//1 1781//1 1756//1
+f 1756//1 1781//1 1757//1
+f 1781//1 1782//1 1757//1
+f 1757//1 1782//1 1758//1
+f 1782//1 1783//1 1758//1
+f 1758//1 1783//1 1759//1
+f 1783//1 1784//1 1759//1
+f 1759//1 1784//1 1760//1
+f 1784//1 1785//1 1760//1
+f 1760//1 1785//1 1761//1
+f 1785//1 1786//1 1761//1
+f 1761//1 1786//1 1762//1
+f 1786//1 1787//1 1762//1
+f 1762//1 1787//1 1763//1
+f 1787//1 1788//1 1763//1
+f 1763//1 1788//1 1764//1
+f 1788//1 1789//1 1764//1
+f 1764//1 1789//1 1765//1
+f 1789//1 1790//1 1765//1
+f 1765//1 1790//1 1766//1
+f 1790//1 1791//1 1766//1
+f 1766//1 1791//1 1767//1
+f 1791//1 1792//1 1767//1
+f 1767//1 1792//1 1768//1
+f 1792//1 1793//1 1768//1
+f 1768//1 1793//1 1769//1
+f 1793//1 1794//1 1769//1
+f 1769//1 1794//1 1770//1
+f 1794//1 1795//1 1770//1
+f 1770//1 1795//1 1771//1
+f 1795//1 1796//1 1771//1
+f 1771//1 1796//1 1772//1
+f 1796//1 1797//1 1772//1
+f 1772//1 1797//1 1773//1
+f 1797//1 1798//1 1773//1
+f 1773//1 1798//1 1774//1
+f 1798//1 1799//1 1774//1
+f 1774//1 1799//1 1775//1
+f 1799//1 1800//1 1775//1
+f 1775//1 1800//1 1776//1
+f 1800//1 1801//1 1776//1
+f 1776//1 1801//1 1777//1
+f 1801//1 1802//1 1777//1
+f 1777//1 1802//1 1778//1
+f 1802//1 1803//1 1778//1
+f 1778//1 1803//1 1779//1
+f 1803//1 1804//1 1779//1
+f 1779//1 1804//1 30//1
+f 1804//1 29//1 30//1
+f 80//1 1805//1 1780//1
+f 1805//1 1806//1 1780//1
+f 1780//1 1806//1 1781//1
+f 1806//1 1807//1 1781//1
+f 1781//1 1807//1 1782//1
+f 1807//1 1808//1 1782//1
+f 1782//1 1808//1 1783//1
+f 1808//1 1809//1 1783//1
+f 1783//1 1809//1 1784//1
+f 1809//1 1810//1 1784//1
+f 1784//1 1810//1 1785//1
+f 1810//1 1811//1 1785//1
+f 1785//1 1811//1 1786//1
+f 1811//1 1812//1 1786//1
+f 1786//1 1812//1 1787//1
+f 1812//1 1813//1 1787//1
+f 1787//1 1813//1 1788//1
+f 1813//1 1814//1 1788//1
+f 1788//1 1814//1 1789//1
+f 1814//1 1815//1 1789//1
+f 1789//1 1815//1 1790//1
+f 1815//1 1816//1 1790//1
+f 1790//1 1816//1 1791//1
+f 1816//1 1817//1 1791//1
+f 1791//1 1817//1 1792//1
+f 1817//1 1818//1 1792//1
+f 1792//1 1818//1 1793//1
+f 1818//1 1819//1 1793//1
+f 1793//1 1819//1 1794//1
+f 1819//1 1820//1 1794//1
+f 1794//1 1820//1 1795//1
+f 1820//1 1821//1 1795//1
+f 1795//1 1821//1 1796//1
+f 1821//1 1822//1 1796//1
+f 1796//1 1822//1 1797//1
+f 1822//1 1823//1 1797//1
+f 1797//1 1823//1 1798//1
+f 1823//1 1824//1 1798//1
+f 1798//1 1824//1 1799//1
+f 1824//1 1825//1 1799//1
+f 1799//1 1825//1 1800//1
+f 1825//1 1826//1 1800//1
+f 1800//1 1826//1 1801//1
+f 1826//1 1827//1 1801//1
+f 1801//1 1827//1 1802//1
+f 1827//1 1828//1 1802//1
+f 1802//1 1828//1 1803//1
+f 1828//1 1829//1 1803//1
+f 1803//1 1829//1 1804//1
+f 1829//1 1830//1 1804//1
+f 1804//1 1830//1 29//1
+f 1830//1 28//1 29//1
+f 81//1 1831//1 1805//1
+f 1831//1 1832//1 1805//1
+f 1805//1 1832//1 1806//1
+f 1832//1 1833//1 1806//1
+f 1806//1 1833//1 1807//1
+f 1833//1 1834//1 1807//1
+f 1807//1 1834//1 1808//1
+f 1834//1 1835//1 1808//1
+f 1808//1 1835//1 1809//1
+f 1835//1 1836//1 1809//1
+f 1809//1 1836//1 1810//1
+f 1836//1 1837//1 1810//1
+f 1810//1 1837//1 1811//1
+f 1837//1 1838//1 1811//1
+f 1811//1 1838//1 1812//1
+f 1838//1 1839//1 1812//1
+f 1812//1 1839//1 1813//1
+f 1839//1 1840//1 1813//1
+f 1813//1 1840//1 1814//1
+f 1840//1 1841//1 1814//1
+f 1814//1 1841//1 1815//1
+f 1841//1 1842//1 1815//1
+f 1815//1 1842//1 1816//1
+f 1842//1 1843//1 1816//1
+f 1816//1 1843//1 1817//1
+f 1843//1 1844//1 1817//1
+f 1817//1 1844//1 1818//1
+f 1844//1 1845//1 1818//1
+f 1818//1 1845//1 1819//1
+f 1845//1 1846//1 1819//1
+f 1819//1 1846//1 1820//1
+f 1846//1 1847//1 1820//1
+f 1820//1 1847//1 1821//1
+f 1847//1 1848//1 1821//1
+f 1821//1 1848//1 1822//1
+f 1848//1 1849//1 1822//1
+f 1822//1 1849//1 1823//1
+f 1849//1 1850//1 1823//1
+f 1823//1 1850//1 1824//1
+f 1850//1 1851//1 1824//1
+f 1824//1 1851//1 1825//1
+f 1851//1 1852//1 1825//1
+f 1825//1 1852//1 1826//1
+f 1852//1 1853//1 1826//1
+f 1826//1 1853//1 1827//1
+f 1853//1 1854//1 1827//1
+f 1827//1 1854//1 1828//1
+f 1854//1 1855//1 1828//1
+f 1828//1 1855//1 1829//1
+f 1855//1 1856//1 1829//1
+f 1829//1 1856//1 1830//1
+f 1856//1 1857//1 1830//1
+f 1830//1 1857//1 28//1
+f 1857//1 27//1 28//1
+f 82//1 1858//1 1831//1
+f 1858//1 1859//1 1831//1
+f 1831//1 1859//1 1832//1
+f 1859//1 1860//1 1832//1
+f 1832//1 1860//1 1833//1
+f 1860//1 1861//1 1833//1
+f 1833//1 1861//1 1834//1
+f 1861//1 1862//1 1834//1
+f 1834//1 1862//1 1835//1
+f 1862//1 1863//1 1835//1
+f 1835//1 1863//1 1836//1
+f 1863//1 1864//1 1836//1
+f 1836//1 1864//1 1837//1
+f 1864//1 1865//1 1837//1
+f 1837//1 1865//1 1838//1
+f 1865//1 1866//1 1838//1
+f 1838//1 1866//1 1839//1
+f 1866//1 1867//1 1839//1
+f 1839//1 1867//1 1840//1
+f 1867//1 1868//1 1840//1
+f 1840//1 1868//1 1841//1
+f 1868//1 1869//1 1841//1
+f 1841//1 1869//1 1842//1
+f 1869//1 1870//1 1842//1
+f 1842//1 1870//1 1843//1
+f 1870//1 1871//1 1843//1
+f 1843//1 1871//1 1844//1
+f 1871//1 1872//1 1844//1
+f 1844//1 1872//1 1845//1
+f 1872//1 1873//1 1845//1
+f 1845//1 1873//1 1846//1
+f 1873//1 1874//1 1846//1
+f 1846//1 1874//1 1847//1
+f 1874//1 1875//1 1847//1
+f 1847//1 1875//1 1848//1
+f 1875//1 1876//1 1848//1
+f 1848//1 1876//1 1849//1
+f 1876//1 1877//1 1849//1
+f 1849//1 1877//1 1850//1
+f 1877//1 1878//1 1850//1
+f 1850//1 1878//1 1851//1
+f 1878//1 1879//1 1851//1
+f 1851//1 1879//1 1852//1
+f 1879//1 1880//1 1852//1
+f 1852//1 1880//1 1853//1
+f 1880//1 1881//1 1853//1
+f 1853//1 1881//1 1854//1
+f 1881//1 1882//1 1854//1
+f 1854//1 1882//1 1855//1
+f 1882//1 1883//1 1855//1
+f 1855//1 1883//1 1856//1
+f 1883//1 1884//1 1856//1
+f 1856//1 1884//1 1857//1
+f 1884//1 1885//1 1857//1
+f 1857//1 1885//1 27//1
+f 1885//1 26//1 27//1
+f 83//1 1886//1 1858//1
+f 1886//1 1887//1 1858//1
+f 1858//1 1887//1 1859//1
+f 1887//1 1888//1 1859//1
+f 1859//1 1888//1 1860//1
+f 1888//1 1889//1 1860//1
+f 1860//1 1889//1 1861//1
+f 1889//1 1890//1 1861//1
+f 1861//1 1890//1 1862//1
+f 1890//1 1891//1 1862//1
+f 1862//1 1891//1 1863//1
+f 1891//1 1892//1 1863//1
+f 1863//1 1892//1 1864//1
+f 1892//1 1893//1 1864//1
+f 1864//1 1893//1 1865//1
+f 1893//1 1894//1 1865//1
+f 1865//1 1894//1 1866//1
+f 1894//1 1895//1 1866//1
+f 1866//1 1895//1 1867//1
+f 1895//1 1896//1 1867//1
+f 1867//1 1896//1 1868//1
+f 1896//1 1897//1 1868//1
+f 1868//1 1897//1 1869//1
+f 1897//1 1898//1 1869//1
+f 1869//1 1898//1 1870//1
+f 1898//1 1899//1 1870//1
+f 1870//1 1899//1 1871//1
+f 1899//1 1900//1 1871//1
+f 1871//1 1900//1 1872//1
+f 1900//1 1901//1 1872//1
+f 1872//1 1901//1 1873//1
+f 1901//1 1902//1 1873//1
+f 1873//1 1902//1 1874//1
+f 1902//1 1903//1 1874//1
+f 1874//1 1903//1 1875//1
+f 1903//1 1904//1 1875//1
+f 1875//1 1904//1 1876//1
+f 1904//1 1905//1 1876//1
+f 1876//1 1905//1 1877//1
+f 1905//1 1906//1 1877//1
+f 1877//1 1906//1 1878//1
+f 1906//1 1907//1 1878//1
+f 1878//1 1907//1 1879//1
+f 1907//1 1908//1 1879//1
+f 1879//1 1908//1 1880//1
+f 1908//1 1909//1 1880//1
+f 1880//1 1909//1 1881//1
+f 1909//1 1910//1 1881//1
+f 1881//1 1910//1 1882//1
+f 1910//1 1911//1 1882//1
+f 1882//1 1911//1 1883//1
+f 1911//1 1912//1 1883//1
+f 1883//1 1912//1 1884//1
+f 1912//1 1913//1 1884//1
+f 1884//1 1913//1 1885//1
+f 1913//1 1914//1 1885//1
+f 1885//1 1914//1 26//1
+f 1914//1 25//1 26//1
+f 84//1 1915//1 1886//1
+f 1915//1 1916//1 1886//1
+f 1886//1 1916//1 1887//1
+f 1916//1 1917//1 1887//1
+f 1887//1 1917//1 1888//1
+f 1917//1 1918//1 1888//1
+f 1888//1 1918//1 1889//1
+f 1918//1 1919//1 1889//1
+f 1889//1 1919//1 1890//1
+f 1919//1 1920//1 1890//1
+f 1890//1 1920//1 1891//1
+f 1920//1 1921//1 1891//1
+f 1891//1 1921//1 1892//1
+f 1921//1 1922//1 1892//1
+f 1892//1 1922//1 1893//1
+f 1922//1 1923//1 1893//1
+f 1893//1 1923//1 1894//1
+f 1923//1 1924//1 1894//1
+f 1894//1 1924//1 1895//1
+f 1924//1 1925//1 1895//1
+f 1895//1 1925//1 1896//1
+f 1925//1 1926//1 1896//1
+f 1896//1 1926//1 1897//1
+f 1926//1 1927//1 1897//1
+f 1897//1 1927//1 1898//1
+f 1927//1 1928//1 1898//1
+f 1898//1 1928//1 1899//1
+f 1928//1 1929//1 1899//1
+f 1899//1 1929//1 1900//1
+f 1929//1 1930//1 1900//1
+f 1900//1 1930//1 1901//1
+f 1930//1 1931//1 1901//1
+f 1901//1 1931//1 1902//1
+f 1931//1 1932//1 1902//1
+f 1902//1 1932//1 1903//1
+f 1932//1 1933//1 1903//1
+f 1903//1 1933//1 1904//1
+f 1933//1 1934//1 1904//1
+f 1904//1 1934//1 1905//1
+f 1934//1 1935//1 1905//1
+f 1905//1 1935//1 1906//1
+f 1935//1 1936//1 1906//1
+f 1906//1 1936//1 1907//1
+f 1936//1 1937//1 1907//1
+f 1907//1 1937//1 1908//1
+f 1937//1 1938//1 1908//1
+f 1908//1 1938//1 1909//1
+f 1938//1 1939//1 1909//1
+f 1909//1 1939//1 1910//1
+f 1939//1 1940//1 1910//1
+f 1910//1 1940//1 1911//1
+f 1940//1 1941//1 1911//1
+f 1911//1 1941//1 1912//1
+f 1941//1 1942//1 1912//1
+f 1912//1 1942//1 1913//1
+f 1942//1 1943//1 1913//1
+f 1913//1 1943//1 1914//1
+f 1943//1 1944//1 1914//1
+f 1914//1 1944//1 25//1
+f 1944//1 24//1 25//1
+f 85//1 1945//1 1915//1
+f 1945//1 1946//1 1915//1
+f 1915//1 1946//1 1916//1
+f 1946//1 1947//1 1916//1
+f 1916//1 1947//1 1917//1
+f 1947//1 1948//1 1917//1
+f 1917//1 1948//1 1918//1
+f 1948//1 1949//1 1918//1
+f 1918//1 1949//1 1919//1
+f 1949//1 1950//1 1919//1
+f 1919//1 1950//1 1920//1
+f 1950//1 1951//1 1920//1
+f 1920//1 1951//1 1921//1
+f 1951//1 1952//1 1921//1
+f 1921//1 1952//1 1922//1
+f 1952//1 1953//1 1922//1
+f 1922//1 1953//1 1923//1
+f 1953//1 1954//1 1923//1
+f 1923//1 1954//1 1924//1
+f 1954//1 1955//1 1924//1
+f 1924//1 1955//1 1925//1
+f 1955//1 1956//1 1925//1
+f 1925//1 1956//1 1926//1
+f 1956//1 1957//1 1926//1
+f 1926//1 1957//1 1927//1
+f 1957//1 1958//1 1927//1
+f 1927//1 1958//1 1928//1
+f 1958//1 1959//1 1928//1
+f 1928//1 1959//1 1929//1
+f 1959//1 1960//1 1929//1
+f 1929//1 1960//1 1930//1
+f 1960//1 1961//1 1930//1
+f 1930//1 1961//1 1931//1
+f 1961//1 1962//1 1931//1
+f 1931//1 1962//1 1932//1
+f 1962//1 1963//1 1932//1
+f 1932//1 1963//1 1933//1
+f 1963//1 1964//1 1933//1
+f 1933//1 1964//1 1934//1
+f 1964//1 1965//1 1934//1
+f 1934//1 1965//1 1935//1
+f 1965//1 1966//1 1935//1
+f 1935//1 1966//1 1936//1
+f 1966//1 1967//1 1936//1
+f 1936//1 1967//1 1937//1
+f 1967//1 1968//1 1937//1
+f 1937//1 1968//1 1938//1
+f 1968//1 1969//1 1938//1
+f 1938//1 1969//1 1939//1
+f 1969//1 1970//1 1939//1
+f 1939//1 1970//1 1940//1
+f 1970//1 1971//1 1940//1
+f 1940//1 1971//1 1941//1
+f 1971//1 1972//1 1941//1
+f 1941//1 1972//1 1942//1
+f 1972//1 1973//1 1942//1
+f 1942//1 1973//1 1943//1
+f 1973//1 1974//1 1943//1
+f 1943//1 1974//1 1944//1
+f 1974//1 1975//1 1944//1
+f 1944//1 1975//1 24//1
+f 1975//1 23//1 24//1
+f 86//1 1976//1 1945//1
+f 1976//1 1977//1 1945//1
+f 1945//1 1977//1 1946//1
+f 1977//1 1978//1 1946//1
+f 1946//1 1978//1 1947//1
+f 1978//1 1979//1 1947//1
+f 1947//1 1979//1 1948//1
+f 1979//1 1980//1 1948//1
+f 1948//1 1980//1 1949//1
+f 1980//1 1981//1 1949//1
+f 1949//1 1981//1 1950//1
+f 1981//1 1982//1 1950//1
+f 1950//1 1982//1 1951//1
+f 1982//1 1983//1 1951//1
+f 1951//1 1983//1 1952//1
+f 1983//1 1984//1 1952//1
+f 1952//1 1984//1 1953//1
+f 1984//1 1985//1 1953//1
+f 1953//1 1985//1 1954//1
+f 1985//1 1986//1 1954//1
+f 1954//1 1986//1 1955//1
+f 1986//1 1987//1 1955//1
+f 1955//1 1987//1 1956//1
+f 1987//1 1988//1 1956//1
+f 1956//1 1988//1 1957//1
+f 1988//1 1989//1 1957//1
+f 1957//1 1989//1 1958//1
+f 1989//1 1990//1 1958//1
+f 1958//1 1990//1 1959//1
+f 1990//1 1991//1 1959//1
+f 1959//1 1991//1 1960//1
+f 1991//1 1992//1 1960//1
+f 1960//1 1992//1 1961//1
+f 1992//1 1993//1 1961//1
+f 1961//1 1993//1 1962//1
+f 1993//1 1994//1 1962//1
+f 1962//1 1994//1 1963//1
+f 1994//1 1995//1 1963//1
+f 1963//1 1995//1 1964//1
+f 1995//1 1996//1 1964//1
+f 1964//1 1996//1 1965//1
+f 1996//1 1997//1 1965//1
+f 1965//1 1997//1 1966//1
+f 1997//1 1998//1 1966//1
+f 1966//1 1998//1 1967//1
+f 1998//1 1999//1 1967//1
+f 1967//1 1999//1 1968//1
+f 1999//1 2000//1 1968//1
+f 1968//1 2000//1 1969//1
+f 2000//1 2001//1 1969//1
+f 1969//1 2001//1 1970//1
+f 2001//1 2002//1 1970//1
+f 1970//1 2002//1 1971//1
+f 2002//1 2003//1 1971//1
+f 1971//1 2003//1 1972//1
+f 2003//1 2004//1 1972//1
+f 1972//1 2004//1 1973//1
+f 2004//1 2005//1 1973//1
+f 1973//1 2005//1 1974//1
+f 2005//1 2006//1 1974//1
+f 1974//1 2006//1 1975//1
+f 2006//1 2007//1 1975//1
+f 1975//1 2007//1 23//1
+f 2007//1 22//1 23//1
+f 87//1 2008//1 1976//1
+f 2008//1 2009//1 1976//1
+f 1976//1 2009//1 1977//1
+f 2009//1 2010//1 1977//1
+f 1977//1 2010//1 1978//1
+f 2010//1 2011//1 1978//1
+f 1978//1 2011//1 1979//1
+f 2011//1 2012//1 1979//1
+f 1979//1 2012//1 1980//1
+f 2012//1 2013//1 1980//1
+f 1980//1 2013//1 1981//1
+f 2013//1 2014//1 1981//1
+f 1981//1 2014//1 1982//1
+f 2014//1 2015//1 1982//1
+f 1982//1 2015//1 1983//1
+f 2015//1 2016//1 1983//1
+f 1983//1 2016//1 1984//1
+f 2016//1 2017//1 1984//1
+f 1984//1 2017//1 1985//1
+f 2017//1 2018//1 1985//1
+f 1985//1 2018//1 1986//1
+f 2018//1 2019//1 1986//1
+f 1986//1 2019//1 1987//1
+f 2019//1 2020//1 1987//1
+f 1987//1 2020//1 1988//1
+f 2020//1 2021//1 1988//1
+f 1988//1 2021//1 1989//1
+f 2021//1 2022//1 1989//1
+f 1989//1 2022//1 1990//1
+f 2022//1 2023//1 1990//1
+f 1990//1 2023//1 1991//1
+f 2023//1 2024//1 1991//1
+f 1991//1 2024//1 1992//1
+f 2024//1 2025//1 1992//1
+f 1992//1 2025//1 1993//1
+f 2025//1 2026//1 1993//1
+f 1993//1 2026//1 1994//1
+f 2026//1 2027//1 1994//1
+f 1994//1 2027//1 1995//1
+f 2027//1 2028//1 1995//1
+f 1995//1 2028//1 1996//1
+f 2028//1 2029//1 1996//1
+f 1996//1 2029//1 1997//1
+f 2029//1 2030//1 1997//1
+f 1997//1 2030//1 1998//1
+f 2030//1 2031//1 1998//1
+f 1998//1 2031//1 1999//1
+f 2031//1 2032//1 1999//1
+f 1999//1 2032//1 2000//1
+f 2032//1 2033//1 2000//1
+f 2000//1 2033//1 2001//1
+f 2033//1 2034//1 2001//1
+f 2001//1 2034//1 2002//1
+f 2034//1 2035//1 2002//1
+f 2002//1 2035//1 2003//1
+f 2035//1 2036//1 2003//1
+f 2003//1 2036//1 2004//1
+f 2036//1 2037//1 2004//1
+f 2004//1 2037//1 2005//1
+f 2037//1 2038//1 2005//1
+f 2005//1 2038//1 2006//1
+f 2038//1 2039//1 2006//1
+f 2006//1 2039//1 2007//1
+f 2039//1 2040//1 2007//1
+f 2007//1 2040//1 22//1
+f 2040//1 21//1 22//1
+f 88//1 2041//1 2008//1
+f 2041//1 2042//1 2008//1
+f 2008//1 2042//1 2009//1
+f 2042//1 2043//1 2009//1
+f 2009//1 2043//1 2010//1
+f 2043//1 2044//1 2010//1
+f 2010//1 2044//1 2011//1
+f 2044//1 2045//1 2011//1
+f 2011//1 2045//1 2012//1
+f 2045//1 2046//1 2012//1
+f 2012//1 2046//1 2013//1
+f 2046//1 2047//1 2013//1
+f 2013//1 2047//1 2014//1
+f 2047//1 2048//1 2014//1
+f 2014//1 2048//1 2015//1
+f 2048//1 2049//1 2015//1
+f 2015//1 2049//1 2016//1
+f 2049//1 2050//1 2016//1
+f 2016//1 2050//1 2017//1
+f 2050//1 2051//1 2017//1
+f 2017//1 2051//1 2018//1
+f 2051//1 2052//1 2018//1
+f 2018//1 2052//1 2019//1
+f 2052//1 2053//1 2019//1
+f 2019//1 2053//1 2020//1
+f 2053//1 2054//1 2020//1
+f 2020//1 2054//1 2021//1
+f 2054//1 2055//1 2021//1
+f 2021//1 2055//1 2022//1
+f 2055//1 2056//1 2022//1
+f 2022//1 2056//1 2023//1
+f 2056//1 2057//1 2023//1
+f 2023//1 2057//1 2024//1
+f 2057//1 2058//1 2024//1
+f 2024//1 2058//1 2025//1
+f 2058//1 2059//1 2025//1
+f 2025//1 2059//1 2026//1
+f 2059//1 2060//1 2026//1
+f 2026//1 2060//1 2027//1
+f 2060//1 2061//1 2027//1
+f 2027//1 2061//1 2028//1
+f 2061//1 2062//1 2028//1
+f 2028//1 2062//1 2029//1
+f 2062//1 2063//1 2029//1
+f 2029//1 2063//1 2030//1
+f 2063//1 2064//1 2030//1
+f 2030//1 2064//1 2031//1
+f 2064//1 2065//1 2031//1
+f 2031//1 2065//1 2032//1
+f 2065//1 2066//1 2032//1
+f 2032//1 2066//1 2033//1
+f 2066//1 2067//1 2033//1
+f 2033//1 2067//1 2034//1
+f 2067//1 2068//1 2034//1
+f 2034//1 2068//1 2035//1
+f 2068//1 2069//1 2035//1
+f 2035//1 2069//1 2036//1
+f 2069//1 2070//1 2036//1
+f 2036//1 2070//1 2037//1
+f 2070//1 2071//1 2037//1
+f 2037//1 2071//1 2038//1
+f 2071//1 2072//1 2038//1
+f 2038//1 2072//1 2039//1
+f 2072//1 2073//1 2039//1
+f 2039//1 2073//1 2040//1
+f 2073//1 2074//1 2040//1
+f 2040//1 2074//1 21//1
+f 2074//1 20//1 21//1
+f 89//1 2075//1 2041//1
+f 2075//1 2076//1 2041//1
+f 2041//1 2076//1 2042//1
+f 2076//1 2077//1 2042//1
+f 2042//1 2077//1 2043//1
+f 2077//1 2078//1 2043//1
+f 2043//1 2078//1 2044//1
+f 2078//1 2079//1 2044//1
+f 2044//1 2079//1 2045//1
+f 2079//1 2080//1 2045//1
+f 2045//1 2080//1 2046//1
+f 2080//1 2081//1 2046//1
+f 2046//1 2081//1 2047//1
+f 2081//1 2082//1 2047//1
+f 2047//1 2082//1 2048//1
+f 2082//1 2083//1 2048//1
+f 2048//1 2083//1 2049//1
+f 2083//1 2084//1 2049//1
+f 2049//1 2084//1 2050//1
+f 2084//1 2085//1 2050//1
+f 2050//1 2085//1 2051//1
+f 2085//1 2086//1 2051//1
+f 2051//1 2086//1 2052//1
+f 2086//1 2087//1 2052//1
+f 2052//1 2087//1 2053//1
+f 2087//1 2088//1 2053//1
+f 2053//1 2088//1 2054//1
+f 2088//1 2089//1 2054//1
+f 2054//1 2089//1 2055//1
+f 2089//1 2090//1 2055//1
+f 2055//1 2090//1 2056//1
+f 2090//1 2091//1 2056//1
+f 2056//1 2091//1 2057//1
+f 2091//1 2092//1 2057//1
+f 2057//1 2092//1 2058//1
+f 2092//1 2093//1 2058//1
+f 2058//1 2093//1 2059//1
+f 2093//1 2094//1 2059//1
+f 2059//1 2094//1 2060//1
+f 2094//1 2095//1 2060//1
+f 2060//1 2095//1 2061//1
+f 2095//1 2096//1 2061//1
+f 2061//1 2096//1 2062//1
+f 2096//1 2097//1 2062//1
+f 2062//1 2097//1 2063//1
+f 2097//1 2098//1 2063//1
+f 2063//1 2098//1 2064//1
+f 2098//1 2099//1 2064//1
+f 2064//1 2099//1 2065//1
+f 2099//1 2100//1 2065//1
+f 2065//1 2100//1 2066//1
+f 2100//1 2101//1 2066//1
+f 2066//1 2101//1 2067//1
+f 2101//1 2102//1 2067//1
+f 2067//1 2102//1 2068//1
+f 2102//1 2103//1 2068//1
+f 2068//1 2103//1 2069//1
+f 2103//1 2104//1 2069//1
+f 2069//1 2104//1 2070//1
+f 2104//1 2105//1 2070//1
+f 2070//1 2105//1 2071//1
+f 2105//1 2106//1 2071//1
+f 2071//1 2106//1 2072//1
+f 2106//1 2107//1 2072//1
+f 2072//1 2107//1 2073//1
+f 2107//1 2108//1 2073//1
+f 2073//1 2108//1 2074//1
+f 2108//1 2109//1 2074//1
+f 2074//1 2109//1 20//1
+f 2109//1 19//1 20//1
+f 90//1 2110//1 2075//1
+f 2110//1 2111//1 2075//1
+f 2075//1 2111//1 2076//1
+f 2111//1 2112//1 2076//1
+f 2076//1 2112//1 2077//1
+f 2112//1 2113//1 2077//1
+f 2077//1 2113//1 2078//1
+f 2113//1 2114//1 2078//1
+f 2078//1 2114//1 2079//1
+f 2114//1 2115//1 2079//1
+f 2079//1 2115//1 2080//1
+f 2115//1 2116//1 2080//1
+f 2080//1 2116//1 2081//1
+f 2116//1 2117//1 2081//1
+f 2081//1 2117//1 2082//1
+f 2117//1 2118//1 2082//1
+f 2082//1 2118//1 2083//1
+f 2118//1 2119//1 2083//1
+f 2083//1 2119//1 2084//1
+f 2119//1 2120//1 2084//1
+f 2084//1 2120//1 2085//1
+f 2120//1 2121//1 2085//1
+f 2085//1 2121//1 2086//1
+f 2121//1 2122//1 2086//1
+f 2086//1 2122//1 2087//1
+f 2122//1 2123//1 2087//1
+f 2087//1 2123//1 2088//1
+f 2123//1 2124//1 2088//1
+f 2088//1 2124//1 2089//1
+f 2124//1 2125//1 2089//1
+f 2089//1 2125//1 2090//1
+f 2125//1 2126//1 2090//1
+f 2090//1 2126//1 2091//1
+f 2126//1 2127//1 2091//1
+f 2091//1 2127//1 2092//1
+f 2127//1 2128//1 2092//1
+f 2092//1 2128//1 2093//1
+f 2128//1 2129//1 2093//1
+f 2093//1 2129//1 2094//1
+f 2129//1 2130//1 2094//1
+f 2094//1 2130//1 2095//1
+f 2130//1 2131//1 2095//1
+f 2095//1 2131//1 2096//1
+f 2131//1 2132//1 2096//1
+f 2096//1 2132//1 2097//1
+f 2132//1 2133//1 2097//1
+f 2097//1 2133//1 2098//1
+f 2133//1 2134//1 2098//1
+f 2098//1 2134//1 2099//1
+f 2134//1 2135//1 2099//1
+f 2099//1 2135//1 2100//1
+f 2135//1 2136//1 2100//1
+f 2100//1 2136//1 2101//1
+f 2136//1 2137//1 2101//1
+f 2101//1 2137//1 2102//1
+f 2137//1 2138//1 2102//1
+f 2102//1 2138//1 2103//1
+f 2138//1 2139//1 2103//1
+f 2103//1 2139//1 2104//1
+f 2139//1 2140//1 2104//1
+f 2104//1 2140//1 2105//1
+f 2140//1 2141//1 2105//1
+f 2105//1 2141//1 2106//1
+f 2141//1 2142//1 2106//1
+f 2106//1 2142//1 2107//1
+f 2142//1 2143//1 2107//1
+f 2107//1 2143//1 2108//1
+f 2143//1 2144//1 2108//1
+f 2108//1 2144//1 2109//1
+f 2144//1 2145//1 2109//1
+f 2109//1 2145//1 19//1
+f 2145//1 18//1 19//1
+f 91//1 2146//1 2110//1
+f 2146//1 2147//1 2110//1
+f 2110//1 2147//1 2111//1
+f 2147//1 2148//1 2111//1
+f 2111//1 2148//1 2112//1
+f 2148//1 2149//1 2112//1
+f 2112//1 2149//1 2113//1
+f 2149//1 2150//1 2113//1
+f 2113//1 2150//1 2114//1
+f 2150//1 2151//1 2114//1
+f 2114//1 2151//1 2115//1
+f 2151//1 2152//1 2115//1
+f 2115//1 2152//1 2116//1
+f 2152//1 2153//1 2116//1
+f 2116//1 2153//1 2117//1
+f 2153//1 2154//1 2117//1
+f 2117//1 2154//1 2118//1
+f 2154//1 2155//1 2118//1
+f 2118//1 2155//1 2119//1
+f 2155//1 2156//1 2119//1
+f 2119//1 2156//1 2120//1
+f 2156//1 2157//1 2120//1
+f 2120//1 2157//1 2121//1
+f 2157//1 2158//1 2121//1
+f 2121//1 2158//1 2122//1
+f 2158//1 2159//1 2122//1
+f 2122//1 2159//1 2123//1
+f 2159//1 2160//1 2123//1
+f 2123//1 2160//1 2124//1
+f 2160//1 2161//1 2124//1
+f 2124//1 2161//1 2125//1
+f 2161//1 2162//1 2125//1
+f 2125//1 2162//1 2126//1
+f 2162//1 2163//1 2126//1
+f 2126//1 2163//1 2127//1
+f 2163//1 2164//1 2127//1
+f 2127//1 2164//1 2128//1
+f 2164//1 2165//1 2128//1
+f 2128//1 2165//1 2129//1
+f 2165//1 2166//1 2129//1
+f 2129//1 2166//1 2130//1
+f 2166//1 2167//1 2130//1
+f 2130//1 2167//1 2131//1
+f 2167//1 2168//1 2131//1
+f 2131//1 2168//1 2132//1
+f 2168//1 2169//1 2132//1
+f 2132//1 2169//1 2133//1
+f 2169//1 2170//1 2133//1
+f 2133//1 2170//1 2134//1
+f 2170//1 2171//1 2134//1
+f 2134//1 2171//1 2135//1
+f 2171//1 2172//1 2135//1
+f 2135//1 2172//1 2136//1
+f 2172//1 2173//1 2136//1
+f 2136//1 2173//1 2137//1
+f 2173//1 2174//1 2137//1
+f 2137//1 2174//1 2138//1
+f 2174//1 2175//1 2138//1
+f 2138//1 2175//1 2139//1
+f 2175//1 2176//1 2139//1
+f 2139//1 2176//1 2140//1
+f 2176//1 2177//1 2140//1
+f 2140//1 2177//1 2141//1
+f 2177//1 2178//1 2141//1
+f 2141//1 2178//1 2142//1
+f 2178//1 2179//1 2142//1
+f 2142//1 2179//1 2143//1
+f 2179//1 2180//1 2143//1
+f 2143//1 2180//1 2144//1
+f 2180//1 2181//1 2144//1
+f 2144//1 2181//1 2145//1
+f 2181//1 2182//1 2145//1
+f 2145//1 2182//1 18//1
+f 2182//1 17//1 18//1
+f 92//1 2183//1 2146//1
+f 2183//1 2184//1 2146//1
+f 2146//1 2184//1 2147//1
+f 2184//1 2185//1 2147//1
+f 2147//1 2185//1 2148//1
+f 2185//1 2186//1 2148//1
+f 2148//1 2186//1 2149//1
+f 2186//1 2187//1 2149//1
+f 2149//1 2187//1 2150//1
+f 2187//1 2188//1 2150//1
+f 2150//1 2188//1 2151//1
+f 2188//1 2189//1 2151//1
+f 2151//1 2189//1 2152//1
+f 2189//1 2190//1 2152//1
+f 2152//1 2190//1 2153//1
+f 2190//1 2191//1 2153//1
+f 2153//1 2191//1 2154//1
+f 2191//1 2192//1 2154//1
+f 2154//1 2192//1 2155//1
+f 2192//1 2193//1 2155//1
+f 2155//1 2193//1 2156//1
+f 2193//1 2194//1 2156//1
+f 2156//1 2194//1 2157//1
+f 2194//1 2195//1 2157//1
+f 2157//1 2195//1 2158//1
+f 2195//1 2196//1 2158//1
+f 2158//1 2196//1 2159//1
+f 2196//1 2197//1 2159//1
+f 2159//1 2197//1 2160//1
+f 2197//1 2198//1 2160//1
+f 2160//1 2198//1 2161//1
+f 2198//1 2199//1 2161//1
+f 2161//1 2199//1 2162//1
+f 2199//1 2200//1 2162//1
+f 2162//1 2200//1 2163//1
+f 2200//1 2201//1 2163//1
+f 2163//1 2201//1 2164//1
+f 2201//1 2202//1 2164//1
+f 2164//1 2202//1 2165//1
+f 2202//1 2203//1 2165//1
+f 2165//1 2203//1 2166//1
+f 2203//1 2204//1 2166//1
+f 2166//1 2204//1 2167//1
+f 2204//1 2205//1 2167//1
+f 2167//1 2205//1 2168//1
+f 2205//1 2206//1 2168//1
+f 2168//1 2206//1 2169//1
+f 2206//1 2207//1 2169//1
+f 2169//1 2207//1 2170//1
+f 2207//1 2208//1 2170//1
+f 2170//1 2208//1 2171//1
+f 2208//1 2209//1 2171//1
+f 2171//1 2209//1 2172//1
+f 2209//1 2210//1 2172//1
+f 2172//1 2210//1 2173//1
+f 2210//1 2211//1 2173//1
+f 2173//1 2211//1 2174//1
+f 2211//1 2212//1 2174//1
+f 2174//1 2212//1 2175//1
+f 2212//1 2213//1 2175//1
+f 2175//1 2213//1 2176//1
+f 2213//1 2214//1 2176//1
+f 2176//1 2214//1 2177//1
+f 2214//1 2215//1 2177//1
+f 2177//1 2215//1 2178//1
+f 2215//1 2216//1 2178//1
+f 2178//1 2216//1 2179//1
+f 2216//1 2217//1 2179//1
+f 2179//1 2217//1 2180//1
+f 2217//1 2218//1 2180//1
+f 2180//1 2218//1 2181//1
+f 2218//1 2219//1 2181//1
+f 2181//1 2219//1 2182//1
+f 2219//1 2220//1 2182//1
+f 2182//1 2220//1 17//1
+f 2220//1 16//1 17//1
+f 93//1 2221//1 2183//1
+f 2221//1 2222//1 2183//1
+f 2183//1 2222//1 2184//1
+f 2222//1 2223//1 2184//1
+f 2184//1 2223//1 2185//1
+f 2223//1 2224//1 2185//1
+f 2185//1 2224//1 2186//1
+f 2224//1 2225//1 2186//1
+f 2186//1 2225//1 2187//1
+f 2225//1 2226//1 2187//1
+f 2187//1 2226//1 2188//1
+f 2226//1 2227//1 2188//1
+f 2188//1 2227//1 2189//1
+f 2227//1 2228//1 2189//1
+f 2189//1 2228//1 2190//1
+f 2228//1 2229//1 2190//1
+f 2190//1 2229//1 2191//1
+f 2229//1 2230//1 2191//1
+f 2191//1 2230//1 2192//1
+f 2230//1 2231//1 2192//1
+f 2192//1 2231//1 2193//1
+f 2231//1 2232//1 2193//1
+f 2193//1 2232//1 2194//1
+f 2232//1 2233//1 2194//1
+f 2194//1 2233//1 2195//1
+f 2233//1 2234//1 2195//1
+f 2195//1 2234//1 2196//1
+f 2234//1 2235//1 2196//1
+f 2196//1 2235//1 2197//1
+f 2235//1 2236//1 2197//1
+f 2197//1 2236//1 2198//1
+f 2236//1 2237//1 2198//1
+f 2198//1 2237//1 2199//1
+f 2237//1 2238//1 2199//1
+f 2199//1 2238//1 2200//1
+f 2238//1 2239//1 2200//1
+f 2200//1 2239//1 2201//1
+f 2239//1 2240//1 2201//1
+f 2201//1 2240//1 2202//1
+f 2240//1 2241//1 2202//1
+f 2202//1 2241//1 2203//1
+f 2241//1 2242//1 2203//1
+f 2203//1 2242//1 2204//1
+f 2242//1 2243//1 2204//1
+f 2204//1 2243//1 2205//1
+f 2243//1 2244//1 2205//1
+f 2205//1 2244//1 2206//1
+f 2244//1 2245//1 2206//1
+f 2206//1 2245//1 2207//1
+f 2245//1 2246//1 2207//1
+f 2207//1 2246//1 2208//1
+f 2246//1 2247//1 2208//1
+f 2208//1 2247//1 2209//1
+f 2247//1 2248//1 2209//1
+f 2209//1 2248//1 2210//1
+f 2248//1 2249//1 2210//1
+f 2210//1 2249//1 2211//1
+f 2249//1 2250//1 2211//1
+f 2211//1 2250//1 2212//1
+f 2250//1 2251//1 2212//1
+f 2212//1 2251//1 2213//1
+f 2251//1 2252//1 2213//1
+f 2213//1 2252//1 2214//1
+f 2252//1 2253//1 2214//1
+f 2214//1 2253//1 2215//1
+f 2253//1 2254//1 2215//1
+f 2215//1 2254//1 2216//1
+f 2254//1 2255//1 2216//1
+f 2216//1 2255//1 2217//1
+f 2255//1 2256//1 2217//1
+f 2217//1 2256//1 2218//1
+f 2256//1 2257//1 2218//1
+f 2218//1 2257//1 2219//1
+f 2257//1 2258//1 2219//1
+f 2219//1 2258//1 2220//1
+f 2258//1 2259//1 2220//1
+f 2220//1 2259//1 16//1
+f 2259//1 15//1 16//1
+f 94//1 2260//1 2221//1
+f 2260//1 2261//1 2221//1
+f 2221//1 2261//1 2222//1
+f 2261//1 2262//1 2222//1
+f 2222//1 2262//1 2223//1
+f 2262//1 2263//1 2223//1
+f 2223//1 2263//1 2224//1
+f 2263//1 2264//1 2224//1
+f 2224//1 2264//1 2225//1
+f 2264//1 2265//1 2225//1
+f 2225//1 2265//1 2226//1
+f 2265//1 2266//1 2226//1
+f 2226//1 2266//1 2227//1
+f 2266//1 2267//1 2227//1
+f 2227//1 2267//1 2228//1
+f 2267//1 2268//1 2228//1
+f 2228//1 2268//1 2229//1
+f 2268//1 2269//1 2229//1
+f 2229//1 2269//1 2230//1
+f 2269//1 2270//1 2230//1
+f 2230//1 2270//1 2231//1
+f 2270//1 2271//1 2231//1
+f 2231//1 2271//1 2232//1
+f 2271//1 2272//1 2232//1
+f 2232//1 2272//1 2233//1
+f 2272//1 2273//1 2233//1
+f 2233//1 2273//1 2234//1
+f 2273//1 2274//1 2234//1
+f 2234//1 2274//1 2235//1
+f 2274//1 2275//1 2235//1
+f 2235//1 2275//1 2236//1
+f 2275//1 2276//1 2236//1
+f 2236//1 2276//1 2237//1
+f 2276//1 2277//1 2237//1
+f 2237//1 2277//1 2238//1
+f 2277//1 2278//1 2238//1
+f 2238//1 2278//1 2239//1
+f 2278//1 2279//1 2239//1
+f 2239//1 2279//1 2240//1
+f 2279//1 2280//1 2240//1
+f 2240//1 2280//1 2241//1
+f 2280//1 2281//1 2241//1
+f 2241//1 2281//1 2242//1
+f 2281//1 2282//1 2242//1
+f 2242//1 2282//1 2243//1
+f 2282//1 2283//1 2243//1
+f 2243//1 2283//1 2244//1
+f 2283//1 2284//1 2244//1
+f 2244//1 2284//1 2245//1
+f 2284//1 2285//1 2245//1
+f 2245//1 2285//1 2246//1
+f 2285//1 2286//1 2246//1
+f 2246//1 2286//1 2247//1
+f 2286//1 2287//1 2247//1
+f 2247//1 2287//1 2248//1
+f 2287//1 2288//1 2248//1
+f 2248//1 2288//1 2249//1
+f 2288//1 2289//1 2249//1
+f 2249//1 2289//1 2250//1
+f 2289//1 2290//1 2250//1
+f 2250//1 2290//1 2251//1
+f 2290//1 2291//1 2251//1
+f 2251//1 2291//1 2252//1
+f 2291//1 2292//1 2252//1
+f 2252//1 2292//1 2253//1
+f 2292//1 2293//1 2253//1
+f 2253//1 2293//1 2254//1
+f 2293//1 2294//1 2254//1
+f 2254//1 2294//1 2255//1
+f 2294//1 2295//1 2255//1
+f 2255//1 2295//1 2256//1
+f 2295//1 2296//1 2256//1
+f 2256//1 2296//1 2257//1
+f 2296//1 2297//1 2257//1
+f 2257//1 2297//1 2258//1
+f 2297//1 2298//1 2258//1
+f 2258//1 2298//1 2259//1
+f 2298//1 2299//1 2259//1
+f 2259//1 2299//1 15//1
+f 2299//1 14//1 15//1
+f 95//1 2300//1 2260//1
+f 2300//1 2301//1 2260//1
+f 2260//1 2301//1 2261//1
+f 2301//1 2302//1 2261//1
+f 2261//1 2302//1 2262//1
+f 2302//1 2303//1 2262//1
+f 2262//1 2303//1 2263//1
+f 2303//1 2304//1 2263//1
+f 2263//1 2304//1 2264//1
+f 2304//1 2305//1 2264//1
+f 2264//1 2305//1 2265//1
+f 2305//1 2306//1 2265//1
+f 2265//1 2306//1 2266//1
+f 2306//1 2307//1 2266//1
+f 2266//1 2307//1 2267//1
+f 2307//1 2308//1 2267//1
+f 2267//1 2308//1 2268//1
+f 2308//1 2309//1 2268//1
+f 2268//1 2309//1 2269//1
+f 2309//1 2310//1 2269//1
+f 2269//1 2310//1 2270//1
+f 2310//1 2311//1 2270//1
+f 2270//1 2311//1 2271//1
+f 2311//1 2312//1 2271//1
+f 2271//1 2312//1 2272//1
+f 2312//1 2313//1 2272//1
+f 2272//1 2313//1 2273//1
+f 2313//1 2314//1 2273//1
+f 2273//1 2314//1 2274//1
+f 2314//1 2315//1 2274//1
+f 2274//1 2315//1 2275//1
+f 2315//1 2316//1 2275//1
+f 2275//1 2316//1 2276//1
+f 2316//1 2317//1 2276//1
+f 2276//1 2317//1 2277//1
+f 2317//1 2318//1 2277//1
+f 2277//1 2318//1 2278//1
+f 2318//1 2319//1 2278//1
+f 2278//1 2319//1 2279//1
+f 2319//1 2320//1 2279//1
+f 2279//1 2320//1 2280//1
+f 2320//1 2321//1 2280//1
+f 2280//1 2321//1 2281//1
+f 2321//1 2322//1 2281//1
+f 2281//1 2322//1 2282//1
+f 2322//1 2323//1 2282//1
+f 2282//1 2323//1 2283//1
+f 2323//1 2324//1 2283//1
+f 2283//1 2324//1 2284//1
+f 2324//1 2325//1 2284//1
+f 2284//1 2325//1 2285//1
+f 2325//1 2326//1 2285//1
+f 2285//1 2326//1 2286//1
+f 2326//1 2327//1 2286//1
+f 2286//1 2327//1 2287//1
+f 2327//1 2328//1 2287//1
+f 2287//1 2328//1 2288//1
+f 2328//1 2329//1 2288//1
+f 2288//1 2329//1 2289//1
+f 2329//1 2330//1 2289//1
+f 2289//1 2330//1 2290//1
+f 2330//1 2331//1 2290//1
+f 2290//1 2331//1 2291//1
+f 2331//1 2332//1 2291//1
+f 2291//1 2332//1 2292//1
+f 2332//1 2333//1 2292//1
+f 2292//1 2333//1 2293//1
+f 2333//1 2334//1 2293//1
+f 2293//1 2334//1 2294//1
+f 2334//1 2335//1 2294//1
+f 2294//1 2335//1 2295//1
+f 2335//1 2336//1 2295//1
+f 2295//1 2336//1 2296//1
+f 2336//1 2337//1 2296//1
+f 2296//1 2337//1 2297//1
+f 2337//1 2338//1 2297//1
+f 2297//1 2338//1 2298//1
+f 2338//1 2339//1 2298//1
+f 2298//1 2339//1 2299//1
+f 2339//1 2340//1 2299//1
+f 2299//1 2340//1 14//1
+f 2340//1 13//1 14//1
+f 96//1 2341//1 2300//1
+f 2341//1 2342//1 2300//1
+f 2300//1 2342//1 2301//1
+f 2342//1 2343//1 2301//1
+f 2301//1 2343//1 2302//1
+f 2343//1 2344//1 2302//1
+f 2302//1 2344//1 2303//1
+f 2344//1 2345//1 2303//1
+f 2303//1 2345//1 2304//1
+f 2345//1 2346//1 2304//1
+f 2304//1 2346//1 2305//1
+f 2346//1 2347//1 2305//1
+f 2305//1 2347//1 2306//1
+f 2347//1 2348//1 2306//1
+f 2306//1 2348//1 2307//1
+f 2348//1 2349//1 2307//1
+f 2307//1 2349//1 2308//1
+f 2349//1 2350//1 2308//1
+f 2308//1 2350//1 2309//1
+f 2350//1 2351//1 2309//1
+f 2309//1 2351//1 2310//1
+f 2351//1 2352//1 2310//1
+f 2310//1 2352//1 2311//1
+f 2352//1 2353//1 2311//1
+f 2311//1 2353//1 2312//1
+f 2353//1 2354//1 2312//1
+f 2312//1 2354//1 2313//1
+f 2354//1 2355//1 2313//1
+f 2313//1 2355//1 2314//1
+f 2355//1 2356//1 2314//1
+f 2314//1 2356//1 2315//1
+f 2356//1 2357//1 2315//1
+f 2315//1 2357//1 2316//1
+f 2357//1 2358//1 2316//1
+f 2316//1 2358//1 2317//1
+f 2358//1 2359//1 2317//1
+f 2317//1 2359//1 2318//1
+f 2359//1 2360//1 2318//1
+f 2318//1 2360//1 2319//1
+f 2360//1 2361//1 2319//1
+f 2319//1 2361//1 2320//1
+f 2361//1 2362//1 2320//1
+f 2320//1 2362//1 2321//1
+f 2362//1 2363//1 2321//1
+f 2321//1 2363//1 2322//1
+f 2363//1 2364//1 2322//1
+f 2322//1 2364//1 2323//1
+f 2364//1 2365//1 2323//1
+f 2323//1 2365//1 2324//1
+f 2365//1 2366//1 2324//1
+f 2324//1 2366//1 2325//1
+f 2366//1 2367//1 2325//1
+f 2325//1 2367//1 2326//1
+f 2367//1 2368//1 2326//1
+f 2326//1 2368//1 2327//1
+f 2368//1 2369//1 2327//1
+f 2327//1 2369//1 2328//1
+f 2369//1 2370//1 2328//1
+f 2328//1 2370//1 2329//1
+f 2370//1 2371//1 2329//1
+f 2329//1 2371//1 2330//1
+f 2371//1 2372//1 2330//1
+f 2330//1 2372//1 2331//1
+f 2372//1 2373//1 2331//1
+f 2331//1 2373//1 2332//1
+f 2373//1 2374//1 2332//1
+f 2332//1 2374//1 2333//1
+f 2374//1 2375//1 2333//1
+f 2333//1 2375//1 2334//1
+f 2375//1 2376//1 2334//1
+f 2334//1 2376//1 2335//1
+f 2376//1 2377//1 2335//1
+f 2335//1 2377//1 2336//1
+f 2377//1 2378//1 2336//1
+f 2336//1 2378//1 2337//1
+f 2378//1 2379//1 2337//1
+f 2337//1 2379//1 2338//1
+f 2379//1 2380//1 2338//1
+f 2338//1 2380//1 2339//1
+f 2380//1 2381//1 2339//1
+f 2339//1 2381//1 2340//1
+f 2381//1 2382//1 2340//1
+f 2340//1 2382//1 13//1
+f 2382//1 12//1 13//1
+f 97//1 2383//1 2341//1
+f 2383//1 2384//1 2341//1
+f 2341//1 2384//1 2342//1
+f 2384//1 2385//1 2342//1
+f 2342//1 2385//1 2343//1
+f 2385//1 2386//1 2343//1
+f 2343//1 2386//1 2344//1
+f 2386//1 2387//1 2344//1
+f 2344//1 2387//1 2345//1
+f 2387//1 2388//1 2345//1
+f 2345//1 2388//1 2346//1
+f 2388//1 2389//1 2346//1
+f 2346//1 2389//1 2347//1
+f 2389//1 2390//1 2347//1
+f 2347//1 2390//1 2348//1
+f 2390//1 2391//1 2348//1
+f 2348//1 2391//1 2349//1
+f 2391//1 2392//1 2349//1
+f 2349//1 2392//1 2350//1
+f 2392//1 2393//1 2350//1
+f 2350//1 2393//1 2351//1
+f 2393//1 2394//1 2351//1
+f 2351//1 2394//1 2352//1
+f 2394//1 2395//1 2352//1
+f 2352//1 2395//1 2353//1
+f 2395//1 2396//1 2353//1
+f 2353//1 2396//1 2354//1
+f 2396//1 2397//1 2354//1
+f 2354//1 2397//1 2355//1
+f 2397//1 2398//1 2355//1
+f 2355//1 2398//1 2356//1
+f 2398//1 2399//1 2356//1
+f 2356//1 2399//1 2357//1
+f 2399//1 2400//1 2357//1
+f 2357//1 2400//1 2358//1
+f 2400//1 2401//1 2358//1
+f 2358//1 2401//1 2359//1
+f 2401//1 2402//1 2359//1
+f 2359//1 2402//1 2360//1
+f 2402//1 2403//1 2360//1
+f 2360//1 2403//1 2361//1
+f 2403//1 2404//1 2361//1
+f 2361//1 2404//1 2362//1
+f 2404//1 2405//1 2362//1
+f 2362//1 2405//1 2363//1
+f 2405//1 2406//1 2363//1
+f 2363//1 2406//1 2364//1
+f 2406//1 2407//1 2364//1
+f 2364//1 2407//1 2365//1
+f 2407//1 2408//1 2365//1
+f 2365//1 2408//1 2366//1
+f 2408//1 2409//1 2366//1
+f 2366//1 2409//1 2367//1
+f 2409//1 2410//1 2367//1
+f 2367//1 2410//1 2368//1
+f 2410//1 2411//1 2368//1
+f 2368//1 2411//1 2369//1
+f 2411//1 2412//1 2369//1
+f 2369//1 2412//1 2370//1
+f 2412//1 2413//1 2370//1
+f 2370//1 2413//1 2371//1
+f 2413//1 2414//1 2371//1
+f 2371//1 2414//1 2372//1
+f 2414//1 2415//1 2372//1
+f 2372//1 2415//1 2373//1
+f 2415//1 2416//1 2373//1
+f 2373//1 2416//1 2374//1
+f 2416//1 2417//1 2374//1
+f 2374//1 2417//1 2375//1
+f 2417//1 2418//1 2375//1
+f 2375//1 2418//1 2376//1
+f 2418//1 2419//1 2376//1
+f 2376//1 2419//1 2377//1
+f 2419//1 2420//1 2377//1
+f 2377//1 2420//1 2378//1
+f 2420//1 2421//1 2378//1
+f 2378//1 2421//1 2379//1
+f 2421//1 2422//1 2379//1
+f 2379//1 2422//1 2380//1
+f 2422//1 2423//1 2380//1
+f 2380//1 2423//1 2381//1
+f 2423//1 2424//1 2381//1
+f 2381//1 2424//1 2382//1
+f 2424//1 2425//1 2382//1
+f 2382//1 2425//1 12//1
+f 2425//1 11//1 12//1
+f 98//1 2426//1 2383//1
+f 2426//1 2427//1 2383//1
+f 2383//1 2427//1 2384//1
+f 2427//1 2428//1 2384//1
+f 2384//1 2428//1 2385//1
+f 2428//1 2429//1 2385//1
+f 2385//1 2429//1 2386//1
+f 2429//1 2430//1 2386//1
+f 2386//1 2430//1 2387//1
+f 2430//1 2431//1 2387//1
+f 2387//1 2431//1 2388//1
+f 2431//1 2432//1 2388//1
+f 2388//1 2432//1 2389//1
+f 2432//1 2433//1 2389//1
+f 2389//1 2433//1 2390//1
+f 2433//1 2434//1 2390//1
+f 2390//1 2434//1 2391//1
+f 2434//1 2435//1 2391//1
+f 2391//1 2435//1 2392//1
+f 2435//1 2436//1 2392//1
+f 2392//1 2436//1 2393//1
+f 2436//1 2437//1 2393//1
+f 2393//1 2437//1 2394//1
+f 2437//1 2438//1 2394//1
+f 2394//1 2438//1 2395//1
+f 2438//1 2439//1 2395//1
+f 2395//1 2439//1 2396//1
+f 2439//1 2440//1 2396//1
+f 2396//1 2440//1 2397//1
+f 2440//1 2441//1 2397//1
+f 2397//1 2441//1 2398//1
+f 2441//1 2442//1 2398//1
+f 2398//1 2442//1 2399//1
+f 2442//1 2443//1 2399//1
+f 2399//1 2443//1 2400//1
+f 2443//1 2444//1 2400//1
+f 2400//1 2444//1 2401//1
+f 2444//1 2445//1 2401//1
+f 2401//1 2445//1 2402//1
+f 2445//1 2446//1 2402//1
+f 2402//1 2446//1 2403//1
+f 2446//1 2447//1 2403//1
+f 2403//1 2447//1 2404//1
+f 2447//1 2448//1 2404//1
+f 2404//1 2448//1 2405//1
+f 2448//1 2449//1 2405//1
+f 2405//1 2449//1 2406//1
+f 2449//1 2450//1 2406//1
+f 2406//1 2450//1 2407//1
+f 2450//1 2451//1 2407//1
+f 2407//1 2451//1 2408//1
+f 2451//1 2452//1 2408//1
+f 2408//1 2452//1 2409//1
+f 2452//1 2453//1 2409//1
+f 2409//1 2453//1 2410//1
+f 2453//1 2454//1 2410//1
+f 2410//1 2454//1 2411//1
+f 2454//1 2455//1 2411//1
+f 2411//1 2455//1 2412//1
+f 2455//1 2456//1 2412//1
+f 2412//1 2456//1 2413//1
+f 2456//1 2457//1 2413//1
+f 2413//1 2457//1 2414//1
+f 2457//1 2458//1 2414//1
+f 2414//1 2458//1 2415//1
+f 2458//1 2459//1 2415//1
+f 2415//1 2459//1 2416//1
+f 2459//1 2460//1 2416//1
+f 2416//1 2460//1 2417//1
+f 2460//1 2461//1 2417//1
+f 2417//1 2461//1 2418//1
+f 2461//1 2462//1 2418//1
+f 2418//1 2462//1 2419//1
+f 2462//1 2463//1 2419//1
+f 2419//1 2463//1 2420//1
+f 2463//1 2464//1 2420//1
+f 2420//1 2464//1 2421//1
+f 2464//1 2465//1 2421//1
+f 2421//1 2465//1 2422//1
+f 2465//1 2466//1 2422//1
+f 2422//1 2466//1 2423//1
+f 2466//1 2467//1 2423//1
+f 2423//1 2467//1 2424//1
+f 2467//1 2468//1 2424//1
+f 2424//1 2468//1 2425//1
+f 2468//1 2469//1 2425//1
+f 2425//1 2469//1 11//1
+f 2469//1 10//1 11//1
+f 99//1 2470//1 2426//1
+f 2470//1 2471//1 2426//1
+f 2426//1 2471//1 2427//1
+f 2471//1 2472//1 2427//1
+f 2427//1 2472//1 2428//1
+f 2472//1 2473//1 2428//1
+f 2428//1 2473//1 2429//1
+f 2473//1 2474//1 2429//1
+f 2429//1 2474//1 2430//1
+f 2474//1 2475//1 2430//1
+f 2430//1 2475//1 2431//1
+f 2475//1 2476//1 2431//1
+f 2431//1 2476//1 2432//1
+f 2476//1 2477//1 2432//1
+f 2432//1 2477//1 2433//1
+f 2477//1 2478//1 2433//1
+f 2433//1 2478//1 2434//1
+f 2478//1 2479//1 2434//1
+f 2434//1 2479//1 2435//1
+f 2479//1 2480//1 2435//1
+f 2435//1 2480//1 2436//1
+f 2480//1 2481//1 2436//1
+f 2436//1 2481//1 2437//1
+f 2481//1 2482//1 2437//1
+f 2437//1 2482//1 2438//1
+f 2482//1 2483//1 2438//1
+f 2438//1 2483//1 2439//1
+f 2483//1 2484//1 2439//1
+f 2439//1 2484//1 2440//1
+f 2484//1 2485//1 2440//1
+f 2440//1 2485//1 2441//1
+f 2485//1 2486//1 2441//1
+f 2441//1 2486//1 2442//1
+f 2486//1 2487//1 2442//1
+f 2442//1 2487//1 2443//1
+f 2487//1 2488//1 2443//1
+f 2443//1 2488//1 2444//1
+f 2488//1 2489//1 2444//1
+f 2444//1 2489//1 2445//1
+f 2489//1 2490//1 2445//1
+f 2445//1 2490//1 2446//1
+f 2490//1 2491//1 2446//1
+f 2446//1 2491//1 2447//1
+f 2491//1 2492//1 2447//1
+f 2447//1 2492//1 2448//1
+f 2492//1 2493//1 2448//1
+f 2448//1 2493//1 2449//1
+f 2493//1 2494//1 2449//1
+f 2449//1 2494//1 2450//1
+f 2494//1 2495//1 2450//1
+f 2450//1 2495//1 2451//1
+f 2495//1 2496//1 2451//1
+f 2451//1 2496//1 2452//1
+f 2496//1 2497//1 2452//1
+f 2452//1 2497//1 2453//1
+f 2497//1 2498//1 2453//1
+f 2453//1 2498//1 2454//1
+f 2498//1 2499//1 2454//1
+f 2454//1 2499//1 2455//1
+f 2499//1 2500//1 2455//1
+f 2455//1 2500//1 2456//1
+f 2500//1 2501//1 2456//1
+f 2456//1 2501//1 2457//1
+f 2501//1 2502//1 2457//1
+f 2457//1 2502//1 2458//1
+f 2502//1 2503//1 2458//1
+f 2458//1 2503//1 2459//1
+f 2503//1 2504//1 2459//1
+f 2459//1 2504//1 2460//1
+f 2504//1 2505//1 2460//1
+f 2460//1 2505//1 2461//1
+f 2505//1 2506//1 2461//1
+f 2461//1 2506//1 2462//1
+f 2506//1 2507//1 2462//1
+f 2462//1 2507//1 2463//1
+f 2507//1 2508//1 2463//1
+f 2463//1 2508//1 2464//1
+f 2508//1 2509//1 2464//1
+f 2464//1 2509//1 2465//1
+f 2509//1 2510//1 2465//1
+f 2465//1 2510//1 2466//1
+f 2510//1 2511//1 2466//1
+f 2466//1 2511//1 2467//1
+f 2511//1 2512//1 2467//1
+f 2467//1 2512//1 2468//1
+f 2512//1 2513//1 2468//1
+f 2468//1 2513//1 2469//1
+f 2513//1 2514//1 2469//1
+f 2469//1 2514//1 10//1
+f 2514//1 9//1 10//1
+f 100//1 2515//1 2470//1
+f 2515//1 2516//1 2470//1
+f 2470//1 2516//1 2471//1
+f 2516//1 2517//1 2471//1
+f 2471//1 2517//1 2472//1
+f 2517//1 2518//1 2472//1
+f 2472//1 2518//1 2473//1
+f 2518//1 2519//1 2473//1
+f 2473//1 2519//1 2474//1
+f 2519//1 2520//1 2474//1
+f 2474//1 2520//1 2475//1
+f 2520//1 2521//1 2475//1
+f 2475//1 2521//1 2476//1
+f 2521//1 2522//1 2476//1
+f 2476//1 2522//1 2477//1
+f 2522//1 2523//1 2477//1
+f 2477//1 2523//1 2478//1
+f 2523//1 2524//1 2478//1
+f 2478//1 2524//1 2479//1
+f 2524//1 2525//1 2479//1
+f 2479//1 2525//1 2480//1
+f 2525//1 2526//1 2480//1
+f 2480//1 2526//1 2481//1
+f 2526//1 2527//1 2481//1
+f 2481//1 2527//1 2482//1
+f 2527//1 2528//1 2482//1
+f 2482//1 2528//1 2483//1
+f 2528//1 2529//1 2483//1
+f 2483//1 2529//1 2484//1
+f 2529//1 2530//1 2484//1
+f 2484//1 2530//1 2485//1
+f 2530//1 2531//1 2485//1
+f 2485//1 2531//1 2486//1
+f 2531//1 2532//1 2486//1
+f 2486//1 2532//1 2487//1
+f 2532//1 2533//1 2487//1
+f 2487//1 2533//1 2488//1
+f 2533//1 2534//1 2488//1
+f 2488//1 2534//1 2489//1
+f 2534//1 2535//1 2489//1
+f 2489//1 2535//1 2490//1
+f 2535//1 2536//1 2490//1
+f 2490//1 2536//1 2491//1
+f 2536//1 2537//1 2491//1
+f 2491//1 2537//1 2492//1
+f 2537//1 2538//1 2492//1
+f 2492//1 2538//1 2493//1
+f 2538//1 2539//1 2493//1
+f 2493//1 2539//1 2494//1
+f 2539//1 2540//1 2494//1
+f 2494//1 2540//1 2495//1
+f 2540//1 2541//1 2495//1
+f 2495//1 2541//1 2496//1
+f 2541//1 2542//1 2496//1
+f 2496//1 2542//1 2497//1
+f 2542//1 2543//1 2497//1
+f 2497//1 2543//1 2498//1
+f 2543//1 2544//1 2498//1
+f 2498//1 2544//1 2499//1
+f 2544//1 2545//1 2499//1
+f 2499//1 2545//1 2500//1
+f 2545//1 2546//1 2500//1
+f 2500//1 2546//1 2501//1
+f 2546//1 2547//1 2501//1
+f 2501//1 2547//1 2502//1
+f 2547//1 2548//1 2502//1
+f 2502//1 2548//1 2503//1
+f 2548//1 2549//1 2503//1
+f 2503//1 2549//1 2504//1
+f 2549//1 2550//1 2504//1
+f 2504//1 2550//1 2505//1
+f 2550//1 2551//1 2505//1
+f 2505//1 2551//1 2506//1
+f 2551//1 2552//1 2506//1
+f 2506//1 2552//1 2507//1
+f 2552//1 2553//1 2507//1
+f 2507//1 2553//1 2508//1
+f 2553//1 2554//1 2508//1
+f 2508//1 2554//1 2509//1
+f 2554//1 2555//1 2509//1
+f 2509//1 2555//1 2510//1
+f 2555//1 2556//1 2510//1
+f 2510//1 2556//1 2511//1
+f 2556//1 2557//1 2511//1
+f 2511//1 2557//1 2512//1
+f 2557//1 2558//1 2512//1
+f 2512//1 2558//1 2513//1
+f 2558//1 2559//1 2513//1
+f 2513//1 2559//1 2514//1
+f 2559//1 2560//1 2514//1
+f 2514//1 2560//1 9//1
+f 2560//1 8//1 9//1
+f 101//1 2561//1 2515//1
+f 2561//1 2562//1 2515//1
+f 2515//1 2562//1 2516//1
+f 2562//1 2563//1 2516//1
+f 2516//1 2563//1 2517//1
+f 2563//1 2564//1 2517//1
+f 2517//1 2564//1 2518//1
+f 2564//1 2565//1 2518//1
+f 2518//1 2565//1 2519//1
+f 2565//1 2566//1 2519//1
+f 2519//1 2566//1 2520//1
+f 2566//1 2567//1 2520//1
+f 2520//1 2567//1 2521//1
+f 2567//1 2568//1 2521//1
+f 2521//1 2568//1 2522//1
+f 2568//1 2569//1 2522//1
+f 2522//1 2569//1 2523//1
+f 2569//1 2570//1 2523//1
+f 2523//1 2570//1 2524//1
+f 2570//1 2571//1 2524//1
+f 2524//1 2571//1 2525//1
+f 2571//1 2572//1 2525//1
+f 2525//1 2572//1 2526//1
+f 2572//1 2573//1 2526//1
+f 2526//1 2573//1 2527//1
+f 2573//1 2574//1 2527//1
+f 2527//1 2574//1 2528//1
+f 2574//1 2575//1 2528//1
+f 2528//1 2575//1 2529//1
+f 2575//1 2576//1 2529//1
+f 2529//1 2576//1 2530//1
+f 2576//1 2577//1 2530//1
+f 2530//1 2577//1 2531//1
+f 2577//1 2578//1 2531//1
+f 2531//1 2578//1 2532//1
+f 2578//1 2579//1 2532//1
+f 2532//1 2579//1 2533//1
+f 2579//1 2580//1 2533//1
+f 2533//1 2580//1 2534//1
+f 2580//1 2581//1 2534//1
+f 2534//1 2581//1 2535//1
+f 2581//1 2582//1 2535//1
+f 2535//1 2582//1 2536//1
+f 2582//1 2583//1 2536//1
+f 2536//1 2583//1 2537//1
+f 2583//1 2584//1 2537//1
+f 2537//1 2584//1 2538//1
+f 2584//1 2585//1 2538//1
+f 2538//1 2585//1 2539//1
+f 2585//1 2586//1 2539//1
+f 2539//1 2586//1 2540//1
+f 2586//1 2587//1 2540//1
+f 2540//1 2587//1 2541//1
+f 2587//1 2588//1 2541//1
+f 2541//1 2588//1 2542//1
+f 2588//1 2589//1 2542//1
+f 2542//1 2589//1 2543//1
+f 2589//1 2590//1 2543//1
+f 2543//1 2590//1 2544//1
+f 2590//1 2591//1 2544//1
+f 2544//1 2591//1 2545//1
+f 2591//1 2592//1 2545//1
+f 2545//1 2592//1 2546//1
+f 2592//1 2593//1 2546//1
+f 2546//1 2593//1 2547//1
+f 2593//1 2594//1 2547//1
+f 2547//1 2594//1 2548//1
+f 2594//1 2595//1 2548//1
+f 2548//1 2595//1 2549//1
+f 2595//1 2596//1 2549//1
+f 2549//1 2596//1 2550//1
+f 2596//1 2597//1 2550//1
+f 2550//1 2597//1 2551//1
+f 2597//1 2598//1 2551//1
+f 2551//1 2598//1 2552//1
+f 2598//1 2599//1 2552//1
+f 2552//1 2599//1 2553//1
+f 2599//1 2600//1 2553//1
+f 2553//1 2600//1 2554//1
+f 2600//1 2601//1 2554//1
+f 2554//1 2601//1 2555//1
+f 2601//1 2602//1 2555//1
+f 2555//1 2602//1 2556//1
+f 2602//1 2603//1 2556//1
+f 2556//1 2603//1 2557//1
+f 2603//1 2604//1 2557//1
+f 2557//1 2604//1 2558//1
+f 2604//1 2605//1 2558//1
+f 2558//1 2605//1 2559//1
+f 2605//1 2606//1 2559//1
+f 2559//1 2606//1 2560//1
+f 2606//1 2607//1 2560//1
+f 2560//1 2607//1 8//1
+f 2607//1 7//1 8//1
+f 102//1 2608//1 2561//1
+f 2608//1 2609//1 2561//1
+f 2561//1 2609//1 2562//1
+f 2609//1 2610//1 2562//1
+f 2562//1 2610//1 2563//1
+f 2610//1 2611//1 2563//1
+f 2563//1 2611//1 2564//1
+f 2611//1 2612//1 2564//1
+f 2564//1 2612//1 2565//1
+f 2612//1 2613//1 2565//1
+f 2565//1 2613//1 2566//1
+f 2613//1 2614//1 2566//1
+f 2566//1 2614//1 2567//1
+f 2614//1 2615//1 2567//1
+f 2567//1 2615//1 2568//1
+f 2615//1 2616//1 2568//1
+f 2568//1 2616//1 2569//1
+f 2616//1 2617//1 2569//1
+f 2569//1 2617//1 2570//1
+f 2617//1 2618//1 2570//1
+f 2570//1 2618//1 2571//1
+f 2618//1 2619//1 2571//1
+f 2571//1 2619//1 2572//1
+f 2619//1 2620//1 2572//1
+f 2572//1 2620//1 2573//1
+f 2620//1 2621//1 2573//1
+f 2573//1 2621//1 2574//1
+f 2621//1 2622//1 2574//1
+f 2574//1 2622//1 2575//1
+f 2622//1 2623//1 2575//1
+f 2575//1 2623//1 2576//1
+f 2623//1 2624//1 2576//1
+f 2576//1 2624//1 2577//1
+f 2624//1 2625//1 2577//1
+f 2577//1 2625//1 2578//1
+f 2625//1 2626//1 2578//1
+f 2578//1 2626//1 2579//1
+f 2626//1 2627//1 2579//1
+f 2579//1 2627//1 2580//1
+f 2627//1 2628//1 2580//1
+f 2580//1 2628//1 2581//1
+f 2628//1 2629//1 2581//1
+f 2581//1 2629//1 2582//1
+f 2629//1 2630//1 2582//1
+f 2582//1 2630//1 2583//1
+f 2630//1 2631//1 2583//1
+f 2583//1 2631//1 2584//1
+f 2631//1 2632//1 2584//1
+f 2584//1 2632//1 2585//1
+f 2632//1 2633//1 2585//1
+f 2585//1 2633//1 2586//1
+f 2633//1 2634//1 2586//1
+f 2586//1 2634//1 2587//1
+f 2634//1 2635//1 2587//1
+f 2587//1 2635//1 2588//1
+f 2635//1 2636//1 2588//1
+f 2588//1 2636//1 2589//1
+f 2636//1 2637//1 2589//1
+f 2589//1 2637//1 2590//1
+f 2637//1 2638//1 2590//1
+f 2590//1 2638//1 2591//1
+f 2638//1 2639//1 2591//1
+f 2591//1 2639//1 2592//1
+f 2639//1 2640//1 2592//1
+f 2592//1 2640//1 2593//1
+f 2640//1 2641//1 2593//1
+f 2593//1 2641//1 2594//1
+f 2641//1 2642//1 2594//1
+f 2594//1 2642//1 2595//1
+f 2642//1 2643//1 2595//1
+f 2595//1 2643//1 2596//1
+f 2643//1 2644//1 2596//1
+f 2596//1 2644//1 2597//1
+f 2644//1 2645//1 2597//1
+f 2597//1 2645//1 2598//1
+f 2645//1 2646//1 2598//1
+f 2598//1 2646//1 2599//1
+f 2646//1 2647//1 2599//1
+f 2599//1 2647//1 2600//1
+f 2647//1 2648//1 2600//1
+f 2600//1 2648//1 2601//1
+f 2648//1 2649//1 2601//1
+f 2601//1 2649//1 2602//1
+f 2649//1 2650//1 2602//1
+f 2602//1 2650//1 2603//1
+f 2650//1 2651//1 2603//1
+f 2603//1 2651//1 2604//1
+f 2651//1 2652//1 2604//1
+f 2604//1 2652//1 2605//1
+f 2652//1 2653//1 2605//1
+f 2605//1 2653//1 2606//1
+f 2653//1 2654//1 2606//1
+f 2606//1 2654//1 2607//1
+f 2654//1 2655//1 2607//1
+f 2607//1 2655//1 7//1
+f 2655//1 6//1 7//1
+f 103//1 2656//1 2608//1
+f 2656//1 2657//1 2608//1
+f 2608//1 2657//1 2609//1
+f 2657//1 2658//1 2609//1
+f 2609//1 2658//1 2610//1
+f 2658//1 2659//1 2610//1
+f 2610//1 2659//1 2611//1
+f 2659//1 2660//1 2611//1
+f 2611//1 2660//1 2612//1
+f 2660//1 2661//1 2612//1
+f 2612//1 2661//1 2613//1
+f 2661//1 2662//1 2613//1
+f 2613//1 2662//1 2614//1
+f 2662//1 2663//1 2614//1
+f 2614//1 2663//1 2615//1
+f 2663//1 2664//1 2615//1
+f 2615//1 2664//1 2616//1
+f 2664//1 2665//1 2616//1
+f 2616//1 2665//1 2617//1
+f 2665//1 2666//1 2617//1
+f 2617//1 2666//1 2618//1
+f 2666//1 2667//1 2618//1
+f 2618//1 2667//1 2619//1
+f 2667//1 2668//1 2619//1
+f 2619//1 2668//1 2620//1
+f 2668//1 2669//1 2620//1
+f 2620//1 2669//1 2621//1
+f 2669//1 2670//1 2621//1
+f 2621//1 2670//1 2622//1
+f 2670//1 2671//1 2622//1
+f 2622//1 2671//1 2623//1
+f 2671//1 2672//1 2623//1
+f 2623//1 2672//1 2624//1
+f 2672//1 2673//1 2624//1
+f 2624//1 2673//1 2625//1
+f 2673//1 2674//1 2625//1
+f 2625//1 2674//1 2626//1
+f 2674//1 2675//1 2626//1
+f 2626//1 2675//1 2627//1
+f 2675//1 2676//1 2627//1
+f 2627//1 2676//1 2628//1
+f 2676//1 2677//1 2628//1
+f 2628//1 2677//1 2629//1
+f 2677//1 2678//1 2629//1
+f 2629//1 2678//1 2630//1
+f 2678//1 2679//1 2630//1
+f 2630//1 2679//1 2631//1
+f 2679//1 2680//1 2631//1
+f 2631//1 2680//1 2632//1
+f 2680//1 2681//1 2632//1
+f 2632//1 2681//1 2633//1
+f 2681//1 2682//1 2633//1
+f 2633//1 2682//1 2634//1
+f 2682//1 2683//1 2634//1
+f 2634//1 2683//1 2635//1
+f 2683//1 2684//1 2635//1
+f 2635//1 2684//1 2636//1
+f 2684//1 2685//1 2636//1
+f 2636//1 2685//1 2637//1
+f 2685//1 2686//1 2637//1
+f 2637//1 2686//1 2638//1
+f 2686//1 2687//1 2638//1
+f 2638//1 2687//1 2639//1
+f 2687//1 2688//1 2639//1
+f 2639//1 2688//1 2640//1
+f 2688//1 2689//1 2640//1
+f 2640//1 2689//1 2641//1
+f 2689//1 2690//1 2641//1
+f 2641//1 2690//1 2642//1
+f 2690//1 2691//1 2642//1
+f 2642//1 2691//1 2643//1
+f 2691//1 2692//1 2643//1
+f 2643//1 2692//1 2644//1
+f 2692//1 2693//1 2644//1
+f 2644//1 2693//1 2645//1
+f 2693//1 2694//1 2645//1
+f 2645//1 2694//1 2646//1
+f 2694//1 2695//1 2646//1
+f 2646//1 2695//1 2647//1
+f 2695//1 2696//1 2647//1
+f 2647//1 2696//1 2648//1
+f 2696//1 2697//1 2648//1
+f 2648//1 2697//1 2649//1
+f 2697//1 2698//1 2649//1
+f 2649//1 2698//1 2650//1
+f 2698//1 2699//1 2650//1
+f 2650//1 2699//1 2651//1
+f 2699//1 2700//1 2651//1
+f 2651//1 2700//1 2652//1
+f 2700//1 2701//1 2652//1
+f 2652//1 2701//1 2653//1
+f 2701//1 2702//1 2653//1
+f 2653//1 2702//1 2654//1
+f 2702//1 2703//1 2654//1
+f 2654//1 2703//1 2655//1
+f 2703//1 2704//1 2655//1
+f 2655//1 2704//1 6//1
+f 2704//1 5//1 6//1
+f 104//1 254//1 2656//1
+f 254//1 253//1 2656//1
+f 2656//1 253//1 2657//1
+f 253//1 252//1 2657//1
+f 2657//1 252//1 2658//1
+f 252//1 251//1 2658//1
+f 2658//1 251//1 2659//1
+f 251//1 250//1 2659//1
+f 2659//1 250//1 2660//1
+f 250//1 249//1 2660//1
+f 2660//1 249//1 2661//1
+f 249//1 248//1 2661//1
+f 2661//1 248//1 2662//1
+f 248//1 247//1 2662//1
+f 2662//1 247//1 2663//1
+f 247//1 246//1 2663//1
+f 2663//1 246//1 2664//1
+f 246//1 245//1 2664//1
+f 2664//1 245//1 2665//1
+f 245//1 244//1 2665//1
+f 2665//1 244//1 2666//1
+f 244//1 243//1 2666//1
+f 2666//1 243//1 2667//1
+f 243//1 242//1 2667//1
+f 2667//1 242//1 2668//1
+f 242//1 241//1 2668//1
+f 2668//1 241//1 2669//1
+f 241//1 240//1 2669//1
+f 2669//1 240//1 2670//1
+f 240//1 239//1 2670//1
+f 2670//1 239//1 2671//1
+f 239//1 238//1 2671//1
+f 2671//1 238//1 2672//1
+f 238//1 237//1 2672//1
+f 2672//1 237//1 2673//1
+f 237//1 236//1 2673//1
+f 2673//1 236//1 2674//1
+f 236//1 235//1 2674//1
+f 2674//1 235//1 2675//1
+f 235//1 234//1 2675//1
+f 2675//1 234//1 2676//1
+f 234//1 233//1 2676//1
+f 2676//1 233//1 2677//1
+f 233//1 232//1 2677//1
+f 2677//1 232//1 2678//1
+f 232//1 231//1 2678//1
+f 2678//1 231//1 2679//1
+f 231//1 230//1 2679//1
+f 2679//1 230//1 2680//1
+f 230//1 229//1 2680//1
+f 2680//1 229//1 2681//1
+f 229//1 228//1 2681//1
+f 2681//1 228//1 2682//1
+f 228//1 227//1 2682//1
+f 2682//1 227//1 2683//1
+f 227//1 226//1 2683//1
+f 2683//1 226//1 2684//1
+f 226//1 225//1 2684//1
+f 2684//1 225//1 2685//1
+f 225//1 224//1 2685//1
+f 2685//1 224//1 2686//1
+f 224//1 223//1 2686//1
+f 2686//1 223//1 2687//1
+f 223//1 222//1 2687//1
+f 2687//1 222//1 2688//1
+f 222//1 221//1 2688//1
+f 2688//1 221//1 2689//1
+f 221//1 220//1 2689//1
+f 2689//1 220//1 2690//1
+f 220//1 219//1 2690//1
+f 2690//1 219//1 2691//1
+f 219//1 218//1 2691//1
+f 2691//1 218//1 2692//1
+f 218//1 217//1 2692//1
+f 2692//1 217//1 2693//1
+f 217//1 216//1 2693//1
+f 2693//1 216//1 2694//1
+f 216//1 215//1 2694//1
+f 2694//1 215//1 2695//1
+f 215//1 214//1 2695//1
+f 2695//1 214//1 2696//1
+f 214//1 213//1 2696//1
+f 2696//1 213//1 2697//1
+f 213//1 212//1 2697//1
+f 2697//1 212//1 2698//1
+f 212//1 211//1 2698//1
+f 2698//1 211//1 2699//1
+f 211//1 210//1 2699//1
+f 2699//1 210//1 2700//1
+f 210//1 209//1 2700//1
+f 2700//1 209//1 2701//1
+f 209//1 208//1 2701//1
+f 2701//1 208//1 2702//1
+f 208//1 207//1 2702//1
+f 2702//1 207//1 2703//1
+f 207//1 206//1 2703//1
+f 2703//1 206//1 2704//1
+f 206//1 205//1 2704//1
+f 2704//1 205//1 5//1
+f 205//1 3//1 5//1
diff --git a/data/torus/torus.mtl b/data/torus/torus.mtl
new file mode 100644
index 000000000..70d3ba1da
--- /dev/null
+++ b/data/torus/torus.mtl
@@ -0,0 +1,10 @@
+# Blender MTL File: 'None'
+# Material Count: 1
+
+newmtl None
+Ns 0
+Ka 0.000000 0.000000 0.000000
+Kd 0.8 0.8 0.8
+Ks 0.8 0.8 0.8
+d 1
+illum 2
diff --git a/data/torus/torus.obj b/data/torus/torus.obj
new file mode 100644
index 000000000..4aafd8fce
--- /dev/null
+++ b/data/torus/torus.obj
@@ -0,0 +1,1446 @@
+# Blender v2.77 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib torus.mtl
+o Torus
+v 1.269537 0.006289 0.009606
+v 1.236043 0.131289 0.009606
+v 1.144537 0.222796 0.009606
+v 1.019537 0.256289 0.009606
+v 0.894537 0.222796 0.009606
+v 0.803031 0.131289 0.009606
+v 0.769537 0.006289 0.009606
+v 0.803031 -0.118711 0.009606
+v 0.894537 -0.210217 0.009606
+v 1.019537 -0.243711 0.009606
+v 1.144537 -0.210217 0.009606
+v 1.236043 -0.118711 0.009606
+v 1.258843 0.006289 -0.153552
+v 1.225636 0.131289 -0.149180
+v 1.134912 0.222796 -0.137236
+v 1.010982 0.256289 -0.120920
+v 0.887051 0.222796 -0.104605
+v 0.796328 0.131289 -0.092661
+v 0.763121 0.006289 -0.088289
+v 0.796328 -0.118711 -0.092661
+v 0.887051 -0.210217 -0.104605
+v 1.010982 -0.243711 -0.120920
+v 1.134912 -0.210217 -0.137236
+v 1.225636 -0.118711 -0.149180
+v 1.226944 0.006289 -0.313918
+v 1.194592 0.131289 -0.305249
+v 1.106204 0.222796 -0.281566
+v 0.985463 0.256289 -0.249213
+v 0.864722 0.222796 -0.216861
+v 0.776334 0.131289 -0.193177
+v 0.743981 0.006289 -0.184509
+v 0.776334 -0.118711 -0.193177
+v 0.864722 -0.210217 -0.216861
+v 0.985463 -0.243711 -0.249213
+v 1.106204 -0.210217 -0.281566
+v 1.194592 -0.118711 -0.305249
+v 1.174387 0.006289 -0.468749
+v 1.143442 0.131289 -0.455931
+v 1.058902 0.222796 -0.420913
+v 0.943417 0.256289 -0.373078
+v 0.827932 0.222796 -0.325242
+v 0.743391 0.131289 -0.290224
+v 0.712447 0.006289 -0.277407
+v 0.743391 -0.118711 -0.290224
+v 0.827932 -0.210217 -0.325242
+v 0.943417 -0.243711 -0.373078
+v 1.058902 -0.210217 -0.420913
+v 1.143442 -0.118711 -0.455931
+v 1.102069 0.006289 -0.615394
+v 1.073062 0.131289 -0.598648
+v 0.993815 0.222796 -0.552894
+v 0.885562 0.256289 -0.490394
+v 0.777309 0.222796 -0.427894
+v 0.698062 0.131289 -0.382141
+v 0.669056 0.006289 -0.365394
+v 0.698062 -0.118711 -0.382141
+v 0.777309 -0.210217 -0.427894
+v 0.885562 -0.243711 -0.490394
+v 0.993815 -0.210217 -0.552894
+v 1.073062 -0.118711 -0.598648
+v 1.011229 0.006289 -0.751346
+v 0.984656 0.131289 -0.730956
+v 0.912059 0.222796 -0.675251
+v 0.812890 0.256289 -0.599156
+v 0.713721 0.222796 -0.523061
+v 0.641124 0.131289 -0.467355
+v 0.614552 0.006289 -0.446965
+v 0.641124 -0.118711 -0.467355
+v 0.713721 -0.210217 -0.523061
+v 0.812890 -0.243711 -0.599156
+v 0.912059 -0.210217 -0.675251
+v 0.984656 -0.118711 -0.730956
+v 0.903420 0.006289 -0.874278
+v 0.879737 0.131289 -0.850594
+v 0.815032 0.222796 -0.785889
+v 0.726644 0.256289 -0.697501
+v 0.638255 0.222796 -0.609113
+v 0.573551 0.131289 -0.544408
+v 0.549867 0.006289 -0.520724
+v 0.573551 -0.118711 -0.544408
+v 0.638255 -0.210217 -0.609113
+v 0.726644 -0.243711 -0.697501
+v 0.815032 -0.210217 -0.785889
+v 0.879737 -0.118711 -0.850594
+v 0.780489 0.006289 -0.982086
+v 0.760099 0.131289 -0.955514
+v 0.704394 0.222796 -0.882917
+v 0.628298 0.256289 -0.783747
+v 0.552203 0.222796 -0.684578
+v 0.496498 0.131289 -0.611982
+v 0.476108 0.006289 -0.585409
+v 0.496498 -0.118711 -0.611982
+v 0.552203 -0.210217 -0.684578
+v 0.628298 -0.243711 -0.783747
+v 0.704394 -0.210217 -0.882917
+v 0.760099 -0.118711 -0.955514
+v 0.644537 0.006289 -1.072926
+v 0.627790 0.131289 -1.043920
+v 0.582037 0.222796 -0.964673
+v 0.519537 0.256289 -0.856420
+v 0.457037 0.222796 -0.748167
+v 0.411284 0.131289 -0.668920
+v 0.394537 0.006289 -0.639913
+v 0.411284 -0.118711 -0.668920
+v 0.457037 -0.210217 -0.748167
+v 0.519537 -0.243711 -0.856420
+v 0.582037 -0.210217 -0.964673
+v 0.627790 -0.118711 -1.043920
+v 0.497891 0.006289 -1.145244
+v 0.485074 0.131289 -1.114299
+v 0.450056 0.222796 -1.029759
+v 0.402221 0.256289 -0.914274
+v 0.354385 0.222796 -0.798789
+v 0.319367 0.131289 -0.714248
+v 0.306550 0.006289 -0.683304
+v 0.319367 -0.118711 -0.714248
+v 0.354385 -0.210217 -0.798789
+v 0.402221 -0.243711 -0.914274
+v 0.450056 -0.210217 -1.029759
+v 0.485074 -0.118711 -1.114299
+v 0.343061 0.006289 -1.197802
+v 0.334392 0.131289 -1.165449
+v 0.310708 0.222796 -1.077061
+v 0.278356 0.256289 -0.956320
+v 0.246004 0.222796 -0.835579
+v 0.222320 0.131289 -0.747191
+v 0.213651 0.006289 -0.714839
+v 0.222320 -0.118711 -0.747191
+v 0.246004 -0.210217 -0.835579
+v 0.278356 -0.243711 -0.956320
+v 0.310708 -0.210217 -1.077061
+v 0.334392 -0.118711 -1.165449
+v 0.182694 0.006289 -1.229700
+v 0.178323 0.131289 -1.196493
+v 0.166379 0.222796 -1.105770
+v 0.150063 0.256289 -0.981839
+v 0.133747 0.222796 -0.857909
+v 0.121803 0.131289 -0.767185
+v 0.117431 0.006289 -0.733978
+v 0.121803 -0.118711 -0.767185
+v 0.133747 -0.210217 -0.857909
+v 0.150063 -0.243711 -0.981839
+v 0.166379 -0.210217 -1.105770
+v 0.178323 -0.118711 -1.196493
+v 0.019537 0.006289 -1.240394
+v 0.019537 0.131289 -1.206901
+v 0.019537 0.222796 -1.115394
+v 0.019537 0.256289 -0.990394
+v 0.019537 0.222796 -0.865394
+v 0.019537 0.131289 -0.773888
+v 0.019537 0.006289 -0.740394
+v 0.019537 -0.118711 -0.773888
+v 0.019537 -0.210217 -0.865394
+v 0.019537 -0.243711 -0.990394
+v 0.019537 -0.210217 -1.115394
+v 0.019537 -0.118711 -1.206901
+v -0.143621 0.006289 -1.229700
+v -0.139249 0.131289 -1.196493
+v -0.127305 0.222796 -1.105770
+v -0.110989 0.256289 -0.981839
+v -0.094674 0.222796 -0.857909
+v -0.082730 0.131289 -0.767185
+v -0.078358 0.006289 -0.733978
+v -0.082730 -0.118711 -0.767185
+v -0.094674 -0.210217 -0.857909
+v -0.110989 -0.243711 -0.981839
+v -0.127305 -0.210217 -1.105770
+v -0.139249 -0.118711 -1.196493
+v -0.303987 0.006289 -1.197802
+v -0.295318 0.131289 -1.165449
+v -0.271634 0.222796 -1.077061
+v -0.239282 0.256289 -0.956320
+v -0.206930 0.222796 -0.835580
+v -0.183246 0.131289 -0.747191
+v -0.174577 0.006289 -0.714839
+v -0.183246 -0.118711 -0.747191
+v -0.206930 -0.210217 -0.835580
+v -0.239282 -0.243711 -0.956320
+v -0.271634 -0.210217 -1.077061
+v -0.295318 -0.118711 -1.165449
+v -0.458818 0.006289 -1.145244
+v -0.446000 0.131289 -1.114300
+v -0.410982 0.222796 -1.029759
+v -0.363147 0.256289 -0.914274
+v -0.315311 0.222796 -0.798789
+v -0.280293 0.131289 -0.714248
+v -0.267476 0.006289 -0.683304
+v -0.280293 -0.118711 -0.714248
+v -0.315311 -0.210217 -0.798789
+v -0.363147 -0.243711 -0.914274
+v -0.410982 -0.210217 -1.029759
+v -0.446000 -0.118711 -1.114300
+v -0.605463 0.006289 -1.072926
+v -0.588716 0.131289 -1.043920
+v -0.542963 0.222796 -0.964673
+v -0.480463 0.256289 -0.856420
+v -0.417963 0.222796 -0.748167
+v -0.372210 0.131289 -0.668920
+v -0.355463 0.006289 -0.639913
+v -0.372210 -0.118711 -0.668920
+v -0.417963 -0.210217 -0.748167
+v -0.480463 -0.243711 -0.856420
+v -0.542963 -0.210217 -0.964673
+v -0.588716 -0.118711 -1.043920
+v -0.741415 0.006289 -0.982086
+v -0.721025 0.131289 -0.955514
+v -0.665320 0.222796 -0.882917
+v -0.589225 0.256289 -0.783748
+v -0.513129 0.222796 -0.684578
+v -0.457424 0.131289 -0.611982
+v -0.437034 0.006289 -0.585409
+v -0.457424 -0.118711 -0.611982
+v -0.513129 -0.210217 -0.684578
+v -0.589225 -0.243711 -0.783748
+v -0.665320 -0.210217 -0.882917
+v -0.721025 -0.118711 -0.955514
+v -0.864347 0.006289 -0.874277
+v -0.840663 0.131289 -0.850594
+v -0.775958 0.222796 -0.785889
+v -0.687570 0.256289 -0.697501
+v -0.599182 0.222796 -0.609113
+v -0.534477 0.131289 -0.544408
+v -0.510793 0.006289 -0.520724
+v -0.534477 -0.118711 -0.544408
+v -0.599182 -0.210217 -0.609113
+v -0.687570 -0.243711 -0.697501
+v -0.775958 -0.210217 -0.785889
+v -0.840663 -0.118711 -0.850594
+v -0.972155 0.006289 -0.751346
+v -0.945583 0.131289 -0.730956
+v -0.872986 0.222796 -0.675251
+v -0.773816 0.256289 -0.599156
+v -0.674647 0.222796 -0.523061
+v -0.602050 0.131289 -0.467355
+v -0.575478 0.006289 -0.446965
+v -0.602050 -0.118711 -0.467355
+v -0.674647 -0.210217 -0.523061
+v -0.773816 -0.243711 -0.599156
+v -0.872986 -0.210217 -0.675251
+v -0.945583 -0.118711 -0.730956
+v -1.062995 0.006289 -0.615395
+v -1.033988 0.131289 -0.598648
+v -0.954742 0.222796 -0.552895
+v -0.846488 0.256289 -0.490395
+v -0.738235 0.222796 -0.427895
+v -0.658988 0.131289 -0.382141
+v -0.629982 0.006289 -0.365395
+v -0.658988 -0.118711 -0.382141
+v -0.738235 -0.210217 -0.427895
+v -0.846488 -0.243711 -0.490395
+v -0.954742 -0.210217 -0.552895
+v -1.033988 -0.118711 -0.598648
+v -1.135312 0.006289 -0.468749
+v -1.104368 0.131289 -0.455931
+v -1.019827 0.222796 -0.420913
+v -0.904343 0.256289 -0.373078
+v -0.788858 0.222796 -0.325242
+v -0.704317 0.131289 -0.290224
+v -0.673373 0.006289 -0.277407
+v -0.704317 -0.118711 -0.290224
+v -0.788858 -0.210217 -0.325242
+v -0.904343 -0.243711 -0.373078
+v -1.019827 -0.210217 -0.420913
+v -1.104368 -0.118711 -0.455931
+v -1.187871 0.006289 -0.313918
+v -1.155518 0.131289 -0.305249
+v -1.067130 0.222796 -0.281566
+v -0.946389 0.256289 -0.249213
+v -0.825648 0.222796 -0.216861
+v -0.737260 0.131289 -0.193177
+v -0.704908 0.006289 -0.184508
+v -0.737260 -0.118711 -0.193177
+v -0.825648 -0.210217 -0.216861
+v -0.946389 -0.243711 -0.249213
+v -1.067130 -0.210217 -0.281566
+v -1.155518 -0.118711 -0.305249
+v -1.219769 0.006289 -0.153552
+v -1.186562 0.131289 -0.149180
+v -1.095839 0.222796 -0.137236
+v -0.971908 0.256289 -0.120921
+v -0.847977 0.222796 -0.104605
+v -0.757254 0.131289 -0.092661
+v -0.724047 0.006289 -0.088289
+v -0.757254 -0.118711 -0.092661
+v -0.847977 -0.210217 -0.104605
+v -0.971908 -0.243711 -0.120921
+v -1.095839 -0.210217 -0.137236
+v -1.186562 -0.118711 -0.149180
+v -1.230463 0.006289 0.009606
+v -1.196970 0.131289 0.009606
+v -1.105463 0.222796 0.009606
+v -0.980463 0.256289 0.009606
+v -0.855463 0.222796 0.009606
+v -0.763957 0.131289 0.009606
+v -0.730463 0.006289 0.009606
+v -0.763957 -0.118711 0.009606
+v -0.855463 -0.210217 0.009606
+v -0.980463 -0.243711 0.009606
+v -1.105463 -0.210217 0.009606
+v -1.196970 -0.118711 0.009606
+v -1.219769 0.006289 0.172764
+v -1.186562 0.131289 0.168392
+v -1.095839 0.222796 0.156448
+v -0.971908 0.256289 0.140132
+v -0.847977 0.222796 0.123816
+v -0.757254 0.131289 0.111872
+v -0.724047 0.006289 0.107500
+v -0.757254 -0.118711 0.111872
+v -0.847977 -0.210217 0.123816
+v -0.971908 -0.243711 0.140132
+v -1.095839 -0.210217 0.156448
+v -1.186562 -0.118711 0.168392
+v -1.187871 0.006289 0.333129
+v -1.155518 0.131289 0.324461
+v -1.067130 0.222796 0.300777
+v -0.946389 0.256289 0.268425
+v -0.825648 0.222796 0.236072
+v -0.737260 0.131289 0.212389
+v -0.704908 0.006289 0.203720
+v -0.737260 -0.118711 0.212389
+v -0.825648 -0.210217 0.236072
+v -0.946389 -0.243711 0.268425
+v -1.067130 -0.210217 0.300777
+v -1.155518 -0.118711 0.324461
+v -1.135313 0.006289 0.487960
+v -1.104369 0.131289 0.475142
+v -1.019828 0.222796 0.440124
+v -0.904343 0.256289 0.392289
+v -0.788858 0.222796 0.344453
+v -0.704317 0.131289 0.309435
+v -0.673373 0.006289 0.296618
+v -0.704317 -0.118711 0.309435
+v -0.788858 -0.210217 0.344453
+v -0.904343 -0.243711 0.392289
+v -1.019828 -0.210217 0.440124
+v -1.104369 -0.118711 0.475142
+v -1.062995 0.006289 0.634606
+v -1.033989 0.131289 0.617859
+v -0.954742 0.222796 0.572106
+v -0.846489 0.256289 0.509606
+v -0.738235 0.222796 0.447106
+v -0.658989 0.131289 0.401352
+v -0.629982 0.006289 0.384606
+v -0.658989 -0.118711 0.401352
+v -0.738235 -0.210217 0.447106
+v -0.846489 -0.243711 0.509606
+v -0.954742 -0.210217 0.572106
+v -1.033989 -0.118711 0.617859
+v -0.972155 0.006289 0.770558
+v -0.945583 0.131289 0.750168
+v -0.872986 0.222796 0.694462
+v -0.773816 0.256289 0.618367
+v -0.674647 0.222796 0.542272
+v -0.602050 0.131289 0.486566
+v -0.575478 0.006289 0.466177
+v -0.602050 -0.118711 0.486566
+v -0.674647 -0.210217 0.542272
+v -0.773816 -0.243711 0.618367
+v -0.872986 -0.210217 0.694462
+v -0.945583 -0.118711 0.750168
+v -0.864347 0.006289 0.893489
+v -0.840663 0.131289 0.869805
+v -0.775958 0.222796 0.805101
+v -0.687570 0.256289 0.716712
+v -0.599182 0.222796 0.628324
+v -0.534477 0.131289 0.563619
+v -0.510793 0.006289 0.539936
+v -0.534477 -0.118711 0.563619
+v -0.599182 -0.210217 0.628324
+v -0.687570 -0.243711 0.716712
+v -0.775958 -0.210217 0.805101
+v -0.840663 -0.118711 0.869805
+v -0.741416 0.006289 1.001297
+v -0.721026 0.131289 0.974725
+v -0.665320 0.222796 0.902128
+v -0.589225 0.256289 0.802959
+v -0.513130 0.222796 0.703790
+v -0.457424 0.131289 0.631193
+v -0.437034 0.006289 0.604621
+v -0.457424 -0.118711 0.631193
+v -0.513130 -0.210217 0.703790
+v -0.589225 -0.243711 0.802959
+v -0.665320 -0.210217 0.902128
+v -0.721026 -0.118711 0.974725
+v -0.605463 0.006289 1.092138
+v -0.588716 0.131289 1.063131
+v -0.542963 0.222796 0.983884
+v -0.480463 0.256289 0.875631
+v -0.417963 0.222796 0.767378
+v -0.372210 0.131289 0.688131
+v -0.355463 0.006289 0.659125
+v -0.372210 -0.118711 0.688131
+v -0.417963 -0.210217 0.767378
+v -0.480463 -0.243711 0.875631
+v -0.542963 -0.210217 0.983884
+v -0.588716 -0.118711 1.063131
+v -0.458818 0.006289 1.164455
+v -0.446000 0.131289 1.133511
+v -0.410982 0.222796 1.048970
+v -0.363147 0.256289 0.933485
+v -0.315311 0.222796 0.818000
+v -0.280293 0.131289 0.733459
+v -0.267476 0.006289 0.702515
+v -0.280293 -0.118711 0.733459
+v -0.315311 -0.210217 0.818000
+v -0.363147 -0.243711 0.933485
+v -0.410982 -0.210217 1.048970
+v -0.446000 -0.118711 1.133511
+v -0.303987 0.006289 1.217013
+v -0.295318 0.131289 1.184660
+v -0.271635 0.222796 1.096272
+v -0.239282 0.256289 0.975531
+v -0.206930 0.222796 0.854791
+v -0.183246 0.131289 0.766402
+v -0.174578 0.006289 0.734050
+v -0.183246 -0.118711 0.766402
+v -0.206930 -0.210217 0.854791
+v -0.239282 -0.243711 0.975531
+v -0.271635 -0.210217 1.096272
+v -0.295318 -0.118711 1.184660
+v -0.143622 0.006289 1.248912
+v -0.139250 0.131289 1.215704
+v -0.127306 0.222796 1.124981
+v -0.110990 0.256289 1.001050
+v -0.094674 0.222796 0.877120
+v -0.082730 0.131289 0.786396
+v -0.078358 0.006289 0.753189
+v -0.082730 -0.118711 0.786396
+v -0.094674 -0.210217 0.877120
+v -0.110990 -0.243711 1.001050
+v -0.127306 -0.210217 1.124981
+v -0.139250 -0.118711 1.215704
+v 0.019537 0.006289 1.259606
+v 0.019537 0.131289 1.226112
+v 0.019537 0.222796 1.134606
+v 0.019537 0.256289 1.009606
+v 0.019537 0.222796 0.884606
+v 0.019537 0.131289 0.793099
+v 0.019537 0.006289 0.759606
+v 0.019537 -0.118711 0.793099
+v 0.019537 -0.210217 0.884606
+v 0.019537 -0.243711 1.009606
+v 0.019537 -0.210217 1.134606
+v 0.019537 -0.118711 1.226112
+v 0.182694 0.006289 1.248912
+v 0.178323 0.131289 1.215705
+v 0.166379 0.222796 1.124981
+v 0.150063 0.256289 1.001051
+v 0.133747 0.222796 0.877120
+v 0.121803 0.131289 0.786396
+v 0.117431 0.006289 0.753189
+v 0.121803 -0.118711 0.786396
+v 0.133747 -0.210217 0.877120
+v 0.150063 -0.243711 1.001051
+v 0.166379 -0.210217 1.124981
+v 0.178323 -0.118711 1.215705
+v 0.343060 0.006289 1.217013
+v 0.334391 0.131289 1.184661
+v 0.310708 0.222796 1.096272
+v 0.278356 0.256289 0.975532
+v 0.246003 0.222796 0.854791
+v 0.222320 0.131289 0.766403
+v 0.213651 0.006289 0.734050
+v 0.222320 -0.118711 0.766403
+v 0.246003 -0.210217 0.854791
+v 0.278356 -0.243711 0.975532
+v 0.310708 -0.210217 1.096272
+v 0.334391 -0.118711 1.184661
+v 0.497891 0.006289 1.164455
+v 0.485074 0.131289 1.133511
+v 0.450056 0.222796 1.048970
+v 0.402221 0.256289 0.933485
+v 0.354385 0.222796 0.818000
+v 0.319367 0.131289 0.733459
+v 0.306550 0.006289 0.702515
+v 0.319367 -0.118711 0.733459
+v 0.354385 -0.210217 0.818000
+v 0.402221 -0.243711 0.933485
+v 0.450056 -0.210217 1.048970
+v 0.485074 -0.118711 1.133511
+v 0.644537 0.006289 1.092137
+v 0.627790 0.131289 1.063131
+v 0.582037 0.222796 0.983884
+v 0.519537 0.256289 0.875631
+v 0.457037 0.222796 0.767378
+v 0.411284 0.131289 0.688131
+v 0.394537 0.006289 0.659125
+v 0.411284 -0.118711 0.688131
+v 0.457037 -0.210217 0.767378
+v 0.519537 -0.243711 0.875631
+v 0.582037 -0.210217 0.983884
+v 0.627790 -0.118711 1.063131
+v 0.780488 0.006289 1.001298
+v 0.760099 0.131289 0.974725
+v 0.704393 0.222796 0.902128
+v 0.628298 0.256289 0.802959
+v 0.552203 0.222796 0.703790
+v 0.496497 0.131289 0.631193
+v 0.476108 0.006289 0.604621
+v 0.496497 -0.118711 0.631193
+v 0.552203 -0.210217 0.703790
+v 0.628298 -0.243711 0.802959
+v 0.704393 -0.210217 0.902128
+v 0.760099 -0.118711 0.974725
+v 0.903420 0.006289 0.893490
+v 0.879736 0.131289 0.869806
+v 0.815032 0.222796 0.805101
+v 0.726643 0.256289 0.716713
+v 0.638255 0.222796 0.628325
+v 0.573550 0.131289 0.563620
+v 0.549867 0.006289 0.539936
+v 0.573550 -0.118711 0.563620
+v 0.638255 -0.210217 0.628325
+v 0.726643 -0.243711 0.716713
+v 0.815032 -0.210217 0.805101
+v 0.879736 -0.118711 0.869806
+v 1.011229 0.006289 0.770557
+v 0.984656 0.131289 0.750168
+v 0.912059 0.222796 0.694462
+v 0.812890 0.256289 0.618367
+v 0.713721 0.222796 0.542272
+v 0.641124 0.131289 0.486566
+v 0.614552 0.006289 0.466177
+v 0.641124 -0.118711 0.486566
+v 0.713721 -0.210217 0.542272
+v 0.812890 -0.243711 0.618367
+v 0.912059 -0.210217 0.694462
+v 0.984656 -0.118711 0.750168
+v 1.102069 0.006289 0.634606
+v 1.073062 0.131289 0.617859
+v 0.993815 0.222796 0.572106
+v 0.885562 0.256289 0.509606
+v 0.777309 0.222796 0.447106
+v 0.698062 0.131289 0.401353
+v 0.669056 0.006289 0.384606
+v 0.698062 -0.118711 0.401353
+v 0.777309 -0.210217 0.447106
+v 0.885562 -0.243711 0.509606
+v 0.993815 -0.210217 0.572106
+v 1.073062 -0.118711 0.617859
+v 1.174386 0.006289 0.487960
+v 1.143442 0.131289 0.475143
+v 1.058901 0.222796 0.440125
+v 0.943416 0.256289 0.392290
+v 0.827931 0.222796 0.344454
+v 0.743391 0.131289 0.309436
+v 0.712446 0.006289 0.296619
+v 0.743391 -0.118711 0.309436
+v 0.827931 -0.210217 0.344454
+v 0.943416 -0.243711 0.392290
+v 1.058901 -0.210217 0.440125
+v 1.143442 -0.118711 0.475143
+v 1.226944 0.006289 0.333129
+v 1.194592 0.131289 0.324460
+v 1.106204 0.222796 0.300777
+v 0.985463 0.256289 0.268424
+v 0.864722 0.222796 0.236072
+v 0.776334 0.131289 0.212389
+v 0.743981 0.006289 0.203720
+v 0.776334 -0.118711 0.212389
+v 0.864722 -0.210217 0.236072
+v 0.985463 -0.243711 0.268424
+v 1.106204 -0.210217 0.300777
+v 1.194592 -0.118711 0.324460
+v 1.258843 0.006289 0.172763
+v 1.225636 0.131289 0.168392
+v 1.134912 0.222796 0.156448
+v 1.010982 0.256289 0.140132
+v 0.887051 0.222796 0.123816
+v 0.796328 0.131289 0.111872
+v 0.763121 0.006289 0.107500
+v 0.796328 -0.118711 0.111872
+v 0.887051 -0.210217 0.123816
+v 1.010982 -0.243711 0.140132
+v 1.134912 -0.210217 0.156448
+v 1.225636 -0.118711 0.168392
+vn 0.9640 0.2583 -0.0632
+vn 0.7063 0.7063 -0.0463
+vn 0.2588 0.9658 -0.0170
+vn -0.2588 0.9658 0.0170
+vn -0.7063 0.7063 0.0463
+vn -0.9640 0.2583 0.0632
+vn -0.9640 -0.2583 0.0632
+vn -0.7063 -0.7063 0.0463
+vn -0.2588 -0.9658 0.0170
+vn 0.2588 -0.9658 -0.0170
+vn 0.7063 -0.7063 -0.0463
+vn 0.9640 -0.2583 -0.0632
+vn 0.9475 0.2583 -0.1885
+vn 0.6943 0.7063 -0.1381
+vn 0.2544 0.9658 -0.0506
+vn -0.2544 0.9658 0.0506
+vn -0.6943 0.7063 0.1381
+vn -0.9475 0.2583 0.1885
+vn -0.9475 -0.2583 0.1885
+vn -0.6943 -0.7063 0.1381
+vn -0.2544 -0.9658 0.0506
+vn 0.2544 -0.9658 -0.0506
+vn 0.6943 -0.7063 -0.1381
+vn 0.9475 -0.2583 -0.1885
+vn 0.9148 0.2583 -0.3105
+vn 0.6703 0.7063 -0.2275
+vn 0.2456 0.9658 -0.0834
+vn -0.2456 0.9658 0.0834
+vn -0.6703 0.7063 0.2275
+vn -0.9148 0.2583 0.3105
+vn -0.9148 -0.2583 0.3105
+vn -0.6703 -0.7063 0.2275
+vn -0.2456 -0.9658 0.0834
+vn 0.2456 -0.9658 -0.0834
+vn 0.6703 -0.7063 -0.2275
+vn 0.9148 -0.2583 -0.3105
+vn 0.8664 0.2583 -0.4273
+vn 0.6349 0.7063 -0.3131
+vn 0.2326 0.9658 -0.1147
+vn -0.2326 0.9658 0.1147
+vn -0.6349 0.7063 0.3131
+vn -0.8664 0.2583 0.4273
+vn -0.8664 -0.2583 0.4273
+vn -0.6349 -0.7063 0.3131
+vn -0.2326 -0.9658 0.1147
+vn 0.2326 -0.9658 -0.1147
+vn 0.6349 -0.7063 -0.3131
+vn 0.8664 -0.2583 -0.4273
+vn 0.8033 0.2583 -0.5367
+vn 0.5886 0.7063 -0.3933
+vn 0.2156 0.9658 -0.1441
+vn -0.2156 0.9658 0.1441
+vn -0.5886 0.7063 0.3933
+vn -0.8033 0.2583 0.5367
+vn -0.8033 -0.2583 0.5367
+vn -0.5886 -0.7063 0.3933
+vn -0.2156 -0.9658 0.1441
+vn 0.2156 -0.9658 -0.1441
+vn 0.5886 -0.7063 -0.3933
+vn 0.8033 -0.2583 -0.5367
+vn 0.7263 0.2583 -0.6370
+vn 0.5322 0.7063 -0.4667
+vn 0.1950 0.9658 -0.1710
+vn -0.1950 0.9658 0.1710
+vn -0.5322 0.7063 0.4667
+vn -0.7263 0.2583 0.6370
+vn -0.7263 -0.2583 0.6370
+vn -0.5322 -0.7063 0.4667
+vn -0.1950 -0.9658 0.1710
+vn 0.1950 -0.9658 -0.1710
+vn 0.5322 -0.7063 -0.4667
+vn 0.7263 -0.2583 -0.6370
+vn 0.6370 0.2583 -0.7263
+vn 0.4667 0.7063 -0.5322
+vn 0.1710 0.9658 -0.1950
+vn -0.1710 0.9658 0.1950
+vn -0.4667 0.7063 0.5322
+vn -0.6370 0.2583 0.7263
+vn -0.6370 -0.2583 0.7263
+vn -0.4667 -0.7063 0.5322
+vn -0.1710 -0.9658 0.1950
+vn 0.1710 -0.9658 -0.1950
+vn 0.4667 -0.7063 -0.5322
+vn 0.6370 -0.2583 -0.7263
+vn 0.5367 0.2583 -0.8033
+vn 0.3933 0.7063 -0.5886
+vn 0.1441 0.9658 -0.2156
+vn -0.1441 0.9658 0.2156
+vn -0.3933 0.7063 0.5886
+vn -0.5367 0.2583 0.8033
+vn -0.5367 -0.2583 0.8033
+vn -0.3933 -0.7063 0.5886
+vn -0.1441 -0.9658 0.2156
+vn 0.1441 -0.9658 -0.2156
+vn 0.3933 -0.7063 -0.5886
+vn 0.5367 -0.2583 -0.8033
+vn 0.4273 0.2583 -0.8664
+vn 0.3131 0.7063 -0.6349
+vn 0.1147 0.9658 -0.2326
+vn -0.1147 0.9658 0.2326
+vn -0.3131 0.7063 0.6349
+vn -0.4273 0.2583 0.8664
+vn -0.4273 -0.2583 0.8664
+vn -0.3131 -0.7063 0.6349
+vn -0.1147 -0.9658 0.2326
+vn 0.1147 -0.9658 -0.2326
+vn 0.3131 -0.7063 -0.6349
+vn 0.4273 -0.2583 -0.8664
+vn 0.3105 0.2583 -0.9148
+vn 0.2275 0.7063 -0.6703
+vn 0.0834 0.9658 -0.2456
+vn -0.0834 0.9658 0.2456
+vn -0.2275 0.7063 0.6703
+vn -0.3105 0.2583 0.9148
+vn -0.3105 -0.2583 0.9148
+vn -0.2275 -0.7063 0.6703
+vn -0.0834 -0.9658 0.2456
+vn 0.0834 -0.9658 -0.2456
+vn 0.2275 -0.7063 -0.6703
+vn 0.3105 -0.2583 -0.9148
+vn 0.1885 0.2583 -0.9475
+vn 0.1381 0.7063 -0.6943
+vn 0.0506 0.9658 -0.2544
+vn -0.0506 0.9658 0.2544
+vn -0.1381 0.7063 0.6943
+vn -0.1885 0.2583 0.9475
+vn -0.1885 -0.2583 0.9475
+vn -0.1381 -0.7063 0.6943
+vn -0.0506 -0.9658 0.2544
+vn 0.0506 -0.9658 -0.2544
+vn 0.1381 -0.7063 -0.6943
+vn 0.1885 -0.2583 -0.9475
+vn 0.0632 0.2583 -0.9640
+vn 0.0463 0.7063 -0.7063
+vn 0.0170 0.9658 -0.2588
+vn -0.0170 0.9658 0.2588
+vn -0.0463 0.7063 0.7063
+vn -0.0632 0.2583 0.9640
+vn -0.0632 -0.2583 0.9640
+vn -0.0463 -0.7063 0.7063
+vn -0.0170 -0.9658 0.2588
+vn 0.0170 -0.9658 -0.2588
+vn 0.0463 -0.7063 -0.7063
+vn 0.0632 -0.2583 -0.9640
+vn -0.0632 0.2583 -0.9640
+vn -0.0463 0.7063 -0.7063
+vn -0.0170 0.9658 -0.2588
+vn 0.0170 0.9658 0.2588
+vn 0.0463 0.7063 0.7063
+vn 0.0632 0.2583 0.9640
+vn 0.0632 -0.2583 0.9640
+vn 0.0463 -0.7063 0.7063
+vn 0.0170 -0.9658 0.2588
+vn -0.0170 -0.9658 -0.2588
+vn -0.0463 -0.7063 -0.7063
+vn -0.0632 -0.2583 -0.9640
+vn -0.1885 0.2583 -0.9475
+vn -0.1381 0.7063 -0.6943
+vn -0.0506 0.9658 -0.2544
+vn 0.0506 0.9658 0.2544
+vn 0.1381 0.7063 0.6943
+vn 0.1885 0.2583 0.9475
+vn 0.1885 -0.2583 0.9475
+vn 0.1381 -0.7063 0.6943
+vn 0.0506 -0.9658 0.2544
+vn -0.0506 -0.9658 -0.2544
+vn -0.1381 -0.7063 -0.6943
+vn -0.1885 -0.2583 -0.9475
+vn -0.3105 0.2583 -0.9148
+vn -0.2275 0.7063 -0.6703
+vn -0.0834 0.9658 -0.2456
+vn 0.0834 0.9658 0.2456
+vn 0.2275 0.7063 0.6703
+vn 0.3105 0.2583 0.9148
+vn 0.3105 -0.2583 0.9148
+vn 0.2275 -0.7063 0.6703
+vn 0.0834 -0.9658 0.2456
+vn -0.0834 -0.9658 -0.2456
+vn -0.2275 -0.7063 -0.6703
+vn -0.3105 -0.2583 -0.9148
+vn -0.4273 0.2583 -0.8664
+vn -0.3131 0.7063 -0.6349
+vn -0.1147 0.9658 -0.2326
+vn 0.1147 0.9658 0.2326
+vn 0.3131 0.7063 0.6349
+vn 0.4273 0.2583 0.8664
+vn 0.4273 -0.2583 0.8664
+vn 0.3131 -0.7063 0.6349
+vn 0.1147 -0.9658 0.2326
+vn -0.1147 -0.9658 -0.2326
+vn -0.3131 -0.7063 -0.6349
+vn -0.4273 -0.2583 -0.8664
+vn -0.5367 0.2583 -0.8033
+vn -0.3933 0.7063 -0.5886
+vn -0.1441 0.9658 -0.2156
+vn 0.1441 0.9658 0.2156
+vn 0.3933 0.7063 0.5886
+vn 0.5367 0.2583 0.8033
+vn 0.5367 -0.2583 0.8033
+vn 0.3933 -0.7063 0.5886
+vn 0.1441 -0.9658 0.2156
+vn -0.1441 -0.9658 -0.2156
+vn -0.3933 -0.7063 -0.5886
+vn -0.5367 -0.2583 -0.8033
+vn -0.6370 0.2583 -0.7263
+vn -0.4667 0.7063 -0.5322
+vn -0.1710 0.9658 -0.1950
+vn 0.1710 0.9658 0.1950
+vn 0.4667 0.7063 0.5322
+vn 0.6370 0.2583 0.7263
+vn 0.6370 -0.2583 0.7263
+vn 0.4667 -0.7063 0.5322
+vn 0.1710 -0.9658 0.1950
+vn -0.1710 -0.9658 -0.1950
+vn -0.4667 -0.7063 -0.5322
+vn -0.6370 -0.2583 -0.7263
+vn -0.7263 0.2583 -0.6370
+vn -0.5322 0.7063 -0.4667
+vn -0.1950 0.9658 -0.1710
+vn 0.1950 0.9658 0.1710
+vn 0.5322 0.7063 0.4667
+vn 0.7263 0.2583 0.6370
+vn 0.7263 -0.2583 0.6370
+vn 0.5322 -0.7063 0.4667
+vn 0.1950 -0.9658 0.1710
+vn -0.1950 -0.9658 -0.1710
+vn -0.5322 -0.7063 -0.4667
+vn -0.7263 -0.2583 -0.6370
+vn -0.8033 0.2583 -0.5367
+vn -0.5886 0.7063 -0.3933
+vn -0.2156 0.9658 -0.1441
+vn 0.2156 0.9658 0.1441
+vn 0.5886 0.7063 0.3933
+vn 0.8033 0.2583 0.5367
+vn 0.8033 -0.2583 0.5367
+vn 0.5886 -0.7063 0.3933
+vn 0.2156 -0.9658 0.1441
+vn -0.2156 -0.9658 -0.1441
+vn -0.5886 -0.7063 -0.3933
+vn -0.8033 -0.2583 -0.5367
+vn -0.8664 0.2583 -0.4273
+vn -0.6349 0.7063 -0.3131
+vn -0.2326 0.9658 -0.1147
+vn 0.2326 0.9658 0.1147
+vn 0.6349 0.7063 0.3131
+vn 0.8664 0.2583 0.4273
+vn 0.8664 -0.2583 0.4273
+vn 0.6349 -0.7063 0.3131
+vn 0.2326 -0.9658 0.1147
+vn -0.2326 -0.9658 -0.1147
+vn -0.6349 -0.7063 -0.3131
+vn -0.8664 -0.2583 -0.4273
+vn -0.9148 0.2583 -0.3105
+vn -0.6703 0.7063 -0.2275
+vn -0.2456 0.9658 -0.0834
+vn 0.2456 0.9658 0.0834
+vn 0.6703 0.7063 0.2275
+vn 0.9148 0.2583 0.3105
+vn 0.9148 -0.2583 0.3105
+vn 0.6703 -0.7063 0.2275
+vn 0.2456 -0.9658 0.0834
+vn -0.2456 -0.9658 -0.0834
+vn -0.6703 -0.7063 -0.2275
+vn -0.9148 -0.2583 -0.3105
+vn -0.9475 0.2583 -0.1885
+vn -0.6943 0.7063 -0.1381
+vn -0.2544 0.9658 -0.0506
+vn 0.2544 0.9658 0.0506
+vn 0.6943 0.7063 0.1381
+vn 0.9475 0.2583 0.1885
+vn 0.9475 -0.2583 0.1885
+vn 0.6943 -0.7063 0.1381
+vn 0.2544 -0.9658 0.0506
+vn -0.2544 -0.9658 -0.0506
+vn -0.6943 -0.7063 -0.1381
+vn -0.9475 -0.2583 -0.1885
+vn -0.9640 0.2583 -0.0632
+vn -0.7063 0.7063 -0.0463
+vn -0.2588 0.9658 -0.0170
+vn 0.2588 0.9658 0.0170
+vn 0.7063 0.7063 0.0463
+vn 0.9640 0.2583 0.0632
+vn 0.9640 -0.2583 0.0632
+vn 0.7063 -0.7063 0.0463
+vn 0.2588 -0.9658 0.0170
+vn -0.2588 -0.9658 -0.0170
+vn -0.7063 -0.7063 -0.0463
+vn -0.9640 -0.2583 -0.0632
+usemtl None
+s off
+f 1//1 13//1 14//1 2//1
+f 2//2 14//2 15//2 3//2
+f 3//3 15//3 16//3 4//3
+f 4//4 16//4 17//4 5//4
+f 5//5 17//5 18//5 6//5
+f 6//6 18//6 19//6 7//6
+f 7//7 19//7 20//7 8//7
+f 8//8 20//8 21//8 9//8
+f 9//9 21//9 22//9 10//9
+f 10//10 22//10 23//10 11//10
+f 11//11 23//11 24//11 12//11
+f 1//12 12//12 24//12 13//12
+f 13//13 25//13 26//13 14//13
+f 14//14 26//14 27//14 15//14
+f 15//15 27//15 28//15 16//15
+f 16//16 28//16 29//16 17//16
+f 17//17 29//17 30//17 18//17
+f 18//18 30//18 31//18 19//18
+f 19//19 31//19 32//19 20//19
+f 20//20 32//20 33//20 21//20
+f 21//21 33//21 34//21 22//21
+f 22//22 34//22 35//22 23//22
+f 23//23 35//23 36//23 24//23
+f 24//24 36//24 25//24 13//24
+f 25//25 37//25 38//25 26//25
+f 26//26 38//26 39//26 27//26
+f 27//27 39//27 40//27 28//27
+f 28//28 40//28 41//28 29//28
+f 29//29 41//29 42//29 30//29
+f 30//30 42//30 43//30 31//30
+f 31//31 43//31 44//31 32//31
+f 32//32 44//32 45//32 33//32
+f 33//33 45//33 46//33 34//33
+f 34//34 46//34 47//34 35//34
+f 35//35 47//35 48//35 36//35
+f 36//36 48//36 37//36 25//36
+f 37//37 49//37 50//37 38//37
+f 38//38 50//38 51//38 39//38
+f 39//39 51//39 52//39 40//39
+f 40//40 52//40 53//40 41//40
+f 41//41 53//41 54//41 42//41
+f 42//42 54//42 55//42 43//42
+f 43//43 55//43 56//43 44//43
+f 44//44 56//44 57//44 45//44
+f 45//45 57//45 58//45 46//45
+f 46//46 58//46 59//46 47//46
+f 47//47 59//47 60//47 48//47
+f 48//48 60//48 49//48 37//48
+f 49//49 61//49 62//49 50//49
+f 50//50 62//50 63//50 51//50
+f 51//51 63//51 64//51 52//51
+f 52//52 64//52 65//52 53//52
+f 53//53 65//53 66//53 54//53
+f 54//54 66//54 67//54 55//54
+f 55//55 67//55 68//55 56//55
+f 56//56 68//56 69//56 57//56
+f 57//57 69//57 70//57 58//57
+f 58//58 70//58 71//58 59//58
+f 59//59 71//59 72//59 60//59
+f 60//60 72//60 61//60 49//60
+f 61//61 73//61 74//61 62//61
+f 62//62 74//62 75//62 63//62
+f 63//63 75//63 76//63 64//63
+f 64//64 76//64 77//64 65//64
+f 65//65 77//65 78//65 66//65
+f 66//66 78//66 79//66 67//66
+f 67//67 79//67 80//67 68//67
+f 68//68 80//68 81//68 69//68
+f 69//69 81//69 82//69 70//69
+f 70//70 82//70 83//70 71//70
+f 71//71 83//71 84//71 72//71
+f 72//72 84//72 73//72 61//72
+f 73//73 85//73 86//73 74//73
+f 74//74 86//74 87//74 75//74
+f 75//75 87//75 88//75 76//75
+f 76//76 88//76 89//76 77//76
+f 77//77 89//77 90//77 78//77
+f 78//78 90//78 91//78 79//78
+f 79//79 91//79 92//79 80//79
+f 80//80 92//80 93//80 81//80
+f 81//81 93//81 94//81 82//81
+f 82//82 94//82 95//82 83//82
+f 83//83 95//83 96//83 84//83
+f 84//84 96//84 85//84 73//84
+f 85//85 97//85 98//85 86//85
+f 86//86 98//86 99//86 87//86
+f 87//87 99//87 100//87 88//87
+f 88//88 100//88 101//88 89//88
+f 89//89 101//89 102//89 90//89
+f 90//90 102//90 103//90 91//90
+f 91//91 103//91 104//91 92//91
+f 92//92 104//92 105//92 93//92
+f 93//93 105//93 106//93 94//93
+f 94//94 106//94 107//94 95//94
+f 95//95 107//95 108//95 96//95
+f 96//96 108//96 97//96 85//96
+f 97//97 109//97 110//97 98//97
+f 98//98 110//98 111//98 99//98
+f 99//99 111//99 112//99 100//99
+f 100//100 112//100 113//100 101//100
+f 101//101 113//101 114//101 102//101
+f 102//102 114//102 115//102 103//102
+f 103//103 115//103 116//103 104//103
+f 104//104 116//104 117//104 105//104
+f 105//105 117//105 118//105 106//105
+f 106//106 118//106 119//106 107//106
+f 107//107 119//107 120//107 108//107
+f 108//108 120//108 109//108 97//108
+f 109//109 121//109 122//109 110//109
+f 110//110 122//110 123//110 111//110
+f 111//111 123//111 124//111 112//111
+f 112//112 124//112 125//112 113//112
+f 113//113 125//113 126//113 114//113
+f 114//114 126//114 127//114 115//114
+f 115//115 127//115 128//115 116//115
+f 116//116 128//116 129//116 117//116
+f 117//117 129//117 130//117 118//117
+f 118//118 130//118 131//118 119//118
+f 119//119 131//119 132//119 120//119
+f 120//120 132//120 121//120 109//120
+f 121//121 133//121 134//121 122//121
+f 122//122 134//122 135//122 123//122
+f 123//123 135//123 136//123 124//123
+f 124//124 136//124 137//124 125//124
+f 125//125 137//125 138//125 126//125
+f 126//126 138//126 139//126 127//126
+f 127//127 139//127 140//127 128//127
+f 128//128 140//128 141//128 129//128
+f 129//129 141//129 142//129 130//129
+f 130//130 142//130 143//130 131//130
+f 131//131 143//131 144//131 132//131
+f 132//132 144//132 133//132 121//132
+f 133//133 145//133 146//133 134//133
+f 134//134 146//134 147//134 135//134
+f 135//135 147//135 148//135 136//135
+f 136//136 148//136 149//136 137//136
+f 137//137 149//137 150//137 138//137
+f 138//138 150//138 151//138 139//138
+f 139//139 151//139 152//139 140//139
+f 140//140 152//140 153//140 141//140
+f 141//141 153//141 154//141 142//141
+f 142//142 154//142 155//142 143//142
+f 143//143 155//143 156//143 144//143
+f 144//144 156//144 145//144 133//144
+f 145//145 157//145 158//145 146//145
+f 146//146 158//146 159//146 147//146
+f 147//147 159//147 160//147 148//147
+f 148//148 160//148 161//148 149//148
+f 149//149 161//149 162//149 150//149
+f 150//150 162//150 163//150 151//150
+f 151//151 163//151 164//151 152//151
+f 152//152 164//152 165//152 153//152
+f 153//153 165//153 166//153 154//153
+f 154//154 166//154 167//154 155//154
+f 155//155 167//155 168//155 156//155
+f 156//156 168//156 157//156 145//156
+f 157//157 169//157 170//157 158//157
+f 158//158 170//158 171//158 159//158
+f 159//159 171//159 172//159 160//159
+f 160//160 172//160 173//160 161//160
+f 161//161 173//161 174//161 162//161
+f 162//162 174//162 175//162 163//162
+f 163//163 175//163 176//163 164//163
+f 164//164 176//164 177//164 165//164
+f 165//165 177//165 178//165 166//165
+f 166//166 178//166 179//166 167//166
+f 167//167 179//167 180//167 168//167
+f 168//168 180//168 169//168 157//168
+f 169//169 181//169 182//169 170//169
+f 170//170 182//170 183//170 171//170
+f 171//171 183//171 184//171 172//171
+f 172//172 184//172 185//172 173//172
+f 173//173 185//173 186//173 174//173
+f 174//174 186//174 187//174 175//174
+f 175//175 187//175 188//175 176//175
+f 176//176 188//176 189//176 177//176
+f 177//177 189//177 190//177 178//177
+f 178//178 190//178 191//178 179//178
+f 179//179 191//179 192//179 180//179
+f 180//180 192//180 181//180 169//180
+f 181//181 193//181 194//181 182//181
+f 182//182 194//182 195//182 183//182
+f 183//183 195//183 196//183 184//183
+f 184//184 196//184 197//184 185//184
+f 185//185 197//185 198//185 186//185
+f 186//186 198//186 199//186 187//186
+f 187//187 199//187 200//187 188//187
+f 188//188 200//188 201//188 189//188
+f 189//189 201//189 202//189 190//189
+f 190//190 202//190 203//190 191//190
+f 191//191 203//191 204//191 192//191
+f 192//192 204//192 193//192 181//192
+f 193//193 205//193 206//193 194//193
+f 194//194 206//194 207//194 195//194
+f 195//195 207//195 208//195 196//195
+f 196//196 208//196 209//196 197//196
+f 197//197 209//197 210//197 198//197
+f 198//198 210//198 211//198 199//198
+f 199//199 211//199 212//199 200//199
+f 200//200 212//200 213//200 201//200
+f 201//201 213//201 214//201 202//201
+f 202//202 214//202 215//202 203//202
+f 203//203 215//203 216//203 204//203
+f 204//204 216//204 205//204 193//204
+f 205//205 217//205 218//205 206//205
+f 206//206 218//206 219//206 207//206
+f 207//207 219//207 220//207 208//207
+f 208//208 220//208 221//208 209//208
+f 209//209 221//209 222//209 210//209
+f 210//210 222//210 223//210 211//210
+f 211//211 223//211 224//211 212//211
+f 212//212 224//212 225//212 213//212
+f 213//213 225//213 226//213 214//213
+f 214//214 226//214 227//214 215//214
+f 215//215 227//215 228//215 216//215
+f 216//216 228//216 217//216 205//216
+f 217//217 229//217 230//217 218//217
+f 218//218 230//218 231//218 219//218
+f 219//219 231//219 232//219 220//219
+f 220//220 232//220 233//220 221//220
+f 221//221 233//221 234//221 222//221
+f 222//222 234//222 235//222 223//222
+f 223//223 235//223 236//223 224//223
+f 224//224 236//224 237//224 225//224
+f 225//225 237//225 238//225 226//225
+f 226//226 238//226 239//226 227//226
+f 227//227 239//227 240//227 228//227
+f 228//228 240//228 229//228 217//228
+f 229//229 241//229 242//229 230//229
+f 230//230 242//230 243//230 231//230
+f 231//231 243//231 244//231 232//231
+f 232//232 244//232 245//232 233//232
+f 233//233 245//233 246//233 234//233
+f 234//234 246//234 247//234 235//234
+f 235//235 247//235 248//235 236//235
+f 236//236 248//236 249//236 237//236
+f 237//237 249//237 250//237 238//237
+f 238//238 250//238 251//238 239//238
+f 239//239 251//239 252//239 240//239
+f 240//240 252//240 241//240 229//240
+f 241//241 253//241 254//241 242//241
+f 242//242 254//242 255//242 243//242
+f 243//243 255//243 256//243 244//243
+f 244//244 256//244 257//244 245//244
+f 245//245 257//245 258//245 246//245
+f 246//246 258//246 259//246 247//246
+f 247//247 259//247 260//247 248//247
+f 248//248 260//248 261//248 249//248
+f 249//249 261//249 262//249 250//249
+f 250//250 262//250 263//250 251//250
+f 251//251 263//251 264//251 252//251
+f 252//252 264//252 253//252 241//252
+f 253//253 265//253 266//253 254//253
+f 254//254 266//254 267//254 255//254
+f 255//255 267//255 268//255 256//255
+f 256//256 268//256 269//256 257//256
+f 257//257 269//257 270//257 258//257
+f 258//258 270//258 271//258 259//258
+f 259//259 271//259 272//259 260//259
+f 260//260 272//260 273//260 261//260
+f 261//261 273//261 274//261 262//261
+f 262//262 274//262 275//262 263//262
+f 263//263 275//263 276//263 264//263
+f 264//264 276//264 265//264 253//264
+f 265//265 277//265 278//265 266//265
+f 266//266 278//266 279//266 267//266
+f 267//267 279//267 280//267 268//267
+f 268//268 280//268 281//268 269//268
+f 269//269 281//269 282//269 270//269
+f 270//270 282//270 283//270 271//270
+f 271//271 283//271 284//271 272//271
+f 272//272 284//272 285//272 273//272
+f 273//273 285//273 286//273 274//273
+f 274//274 286//274 287//274 275//274
+f 275//275 287//275 288//275 276//275
+f 276//276 288//276 277//276 265//276
+f 277//277 289//277 290//277 278//277
+f 278//278 290//278 291//278 279//278
+f 279//279 291//279 292//279 280//279
+f 280//280 292//280 293//280 281//280
+f 281//281 293//281 294//281 282//281
+f 282//282 294//282 295//282 283//282
+f 283//283 295//283 296//283 284//283
+f 284//284 296//284 297//284 285//284
+f 285//285 297//285 298//285 286//285
+f 286//286 298//286 299//286 287//286
+f 287//287 299//287 300//287 288//287
+f 288//288 300//288 289//288 277//288
+f 289//6 301//6 302//6 290//6
+f 290//5 302//5 303//5 291//5
+f 291//4 303//4 304//4 292//4
+f 292//3 304//3 305//3 293//3
+f 293//2 305//2 306//2 294//2
+f 294//1 306//1 307//1 295//1
+f 295//12 307//12 308//12 296//12
+f 296//11 308//11 309//11 297//11
+f 297//10 309//10 310//10 298//10
+f 298//9 310//9 311//9 299//9
+f 299//8 311//8 312//8 300//8
+f 300//7 312//7 301//7 289//7
+f 301//18 313//18 314//18 302//18
+f 302//17 314//17 315//17 303//17
+f 303//16 315//16 316//16 304//16
+f 304//15 316//15 317//15 305//15
+f 305//14 317//14 318//14 306//14
+f 306//13 318//13 319//13 307//13
+f 307//24 319//24 320//24 308//24
+f 308//23 320//23 321//23 309//23
+f 309//22 321//22 322//22 310//22
+f 310//21 322//21 323//21 311//21
+f 311//20 323//20 324//20 312//20
+f 312//19 324//19 313//19 301//19
+f 313//30 325//30 326//30 314//30
+f 314//29 326//29 327//29 315//29
+f 315//28 327//28 328//28 316//28
+f 316//27 328//27 329//27 317//27
+f 317//26 329//26 330//26 318//26
+f 318//25 330//25 331//25 319//25
+f 319//36 331//36 332//36 320//36
+f 320//35 332//35 333//35 321//35
+f 321//34 333//34 334//34 322//34
+f 322//33 334//33 335//33 323//33
+f 323//32 335//32 336//32 324//32
+f 324//31 336//31 325//31 313//31
+f 325//42 337//42 338//42 326//42
+f 326//41 338//41 339//41 327//41
+f 327//40 339//40 340//40 328//40
+f 328//39 340//39 341//39 329//39
+f 329//38 341//38 342//38 330//38
+f 330//37 342//37 343//37 331//37
+f 331//48 343//48 344//48 332//48
+f 332//47 344//47 345//47 333//47
+f 333//46 345//46 346//46 334//46
+f 334//45 346//45 347//45 335//45
+f 335//44 347//44 348//44 336//44
+f 336//43 348//43 337//43 325//43
+f 337//54 349//54 350//54 338//54
+f 338//53 350//53 351//53 339//53
+f 339//52 351//52 352//52 340//52
+f 340//51 352//51 353//51 341//51
+f 341//50 353//50 354//50 342//50
+f 342//49 354//49 355//49 343//49
+f 343//60 355//60 356//60 344//60
+f 344//59 356//59 357//59 345//59
+f 345//58 357//58 358//58 346//58
+f 346//57 358//57 359//57 347//57
+f 347//56 359//56 360//56 348//56
+f 348//55 360//55 349//55 337//55
+f 349//66 361//66 362//66 350//66
+f 350//65 362//65 363//65 351//65
+f 351//64 363//64 364//64 352//64
+f 352//63 364//63 365//63 353//63
+f 353//62 365//62 366//62 354//62
+f 354//61 366//61 367//61 355//61
+f 355//72 367//72 368//72 356//72
+f 356//71 368//71 369//71 357//71
+f 357//70 369//70 370//70 358//70
+f 358//69 370//69 371//69 359//69
+f 359//68 371//68 372//68 360//68
+f 360//67 372//67 361//67 349//67
+f 361//78 373//78 374//78 362//78
+f 362//77 374//77 375//77 363//77
+f 363//76 375//76 376//76 364//76
+f 364//75 376//75 377//75 365//75
+f 365//74 377//74 378//74 366//74
+f 366//73 378//73 379//73 367//73
+f 367//84 379//84 380//84 368//84
+f 368//83 380//83 381//83 369//83
+f 369//82 381//82 382//82 370//82
+f 370//81 382//81 383//81 371//81
+f 371//80 383//80 384//80 372//80
+f 372//79 384//79 373//79 361//79
+f 373//90 385//90 386//90 374//90
+f 374//89 386//89 387//89 375//89
+f 375//88 387//88 388//88 376//88
+f 376//87 388//87 389//87 377//87
+f 377//86 389//86 390//86 378//86
+f 378//85 390//85 391//85 379//85
+f 379//96 391//96 392//96 380//96
+f 380//95 392//95 393//95 381//95
+f 381//94 393//94 394//94 382//94
+f 382//93 394//93 395//93 383//93
+f 383//92 395//92 396//92 384//92
+f 384//91 396//91 385//91 373//91
+f 385//102 397//102 398//102 386//102
+f 386//101 398//101 399//101 387//101
+f 387//100 399//100 400//100 388//100
+f 388//99 400//99 401//99 389//99
+f 389//98 401//98 402//98 390//98
+f 390//97 402//97 403//97 391//97
+f 391//108 403//108 404//108 392//108
+f 392//107 404//107 405//107 393//107
+f 393//106 405//106 406//106 394//106
+f 394//105 406//105 407//105 395//105
+f 395//104 407//104 408//104 396//104
+f 396//103 408//103 397//103 385//103
+f 397//114 409//114 410//114 398//114
+f 398//113 410//113 411//113 399//113
+f 399//112 411//112 412//112 400//112
+f 400//111 412//111 413//111 401//111
+f 401//110 413//110 414//110 402//110
+f 402//109 414//109 415//109 403//109
+f 403//120 415//120 416//120 404//120
+f 404//119 416//119 417//119 405//119
+f 405//118 417//118 418//118 406//118
+f 406//117 418//117 419//117 407//117
+f 407//116 419//116 420//116 408//116
+f 408//115 420//115 409//115 397//115
+f 409//126 421//126 422//126 410//126
+f 410//125 422//125 423//125 411//125
+f 411//124 423//124 424//124 412//124
+f 412//123 424//123 425//123 413//123
+f 413//122 425//122 426//122 414//122
+f 414//121 426//121 427//121 415//121
+f 415//132 427//132 428//132 416//132
+f 416//131 428//131 429//131 417//131
+f 417//130 429//130 430//130 418//130
+f 418//129 430//129 431//129 419//129
+f 419//128 431//128 432//128 420//128
+f 420//127 432//127 421//127 409//127
+f 421//138 433//138 434//138 422//138
+f 422//137 434//137 435//137 423//137
+f 423//136 435//136 436//136 424//136
+f 424//135 436//135 437//135 425//135
+f 425//134 437//134 438//134 426//134
+f 426//133 438//133 439//133 427//133
+f 427//144 439//144 440//144 428//144
+f 428//143 440//143 441//143 429//143
+f 429//142 441//142 442//142 430//142
+f 430//141 442//141 443//141 431//141
+f 431//140 443//140 444//140 432//140
+f 432//139 444//139 433//139 421//139
+f 433//150 445//150 446//150 434//150
+f 434//149 446//149 447//149 435//149
+f 435//148 447//148 448//148 436//148
+f 436//147 448//147 449//147 437//147
+f 437//146 449//146 450//146 438//146
+f 438//145 450//145 451//145 439//145
+f 439//156 451//156 452//156 440//156
+f 440//155 452//155 453//155 441//155
+f 441//154 453//154 454//154 442//154
+f 442//153 454//153 455//153 443//153
+f 443//152 455//152 456//152 444//152
+f 444//151 456//151 445//151 433//151
+f 445//162 457//162 458//162 446//162
+f 446//161 458//161 459//161 447//161
+f 447//160 459//160 460//160 448//160
+f 448//159 460//159 461//159 449//159
+f 449//158 461//158 462//158 450//158
+f 450//157 462//157 463//157 451//157
+f 451//168 463//168 464//168 452//168
+f 452//167 464//167 465//167 453//167
+f 453//166 465//166 466//166 454//166
+f 454//165 466//165 467//165 455//165
+f 455//164 467//164 468//164 456//164
+f 456//163 468//163 457//163 445//163
+f 457//174 469//174 470//174 458//174
+f 458//173 470//173 471//173 459//173
+f 459//172 471//172 472//172 460//172
+f 460//171 472//171 473//171 461//171
+f 461//170 473//170 474//170 462//170
+f 462//169 474//169 475//169 463//169
+f 463//180 475//180 476//180 464//180
+f 464//179 476//179 477//179 465//179
+f 465//178 477//178 478//178 466//178
+f 466//177 478//177 479//177 467//177
+f 467//176 479//176 480//176 468//176
+f 468//175 480//175 469//175 457//175
+f 469//186 481//186 482//186 470//186
+f 470//185 482//185 483//185 471//185
+f 471//184 483//184 484//184 472//184
+f 472//183 484//183 485//183 473//183
+f 473//182 485//182 486//182 474//182
+f 474//181 486//181 487//181 475//181
+f 475//192 487//192 488//192 476//192
+f 476//191 488//191 489//191 477//191
+f 477//190 489//190 490//190 478//190
+f 478//189 490//189 491//189 479//189
+f 479//188 491//188 492//188 480//188
+f 480//187 492//187 481//187 469//187
+f 481//198 493//198 494//198 482//198
+f 482//197 494//197 495//197 483//197
+f 483//196 495//196 496//196 484//196
+f 484//195 496//195 497//195 485//195
+f 485//194 497//194 498//194 486//194
+f 486//193 498//193 499//193 487//193
+f 487//204 499//204 500//204 488//204
+f 488//203 500//203 501//203 489//203
+f 489//202 501//202 502//202 490//202
+f 490//201 502//201 503//201 491//201
+f 491//200 503//200 504//200 492//200
+f 492//199 504//199 493//199 481//199
+f 493//210 505//210 506//210 494//210
+f 494//209 506//209 507//209 495//209
+f 495//208 507//208 508//208 496//208
+f 496//207 508//207 509//207 497//207
+f 497//206 509//206 510//206 498//206
+f 498//205 510//205 511//205 499//205
+f 499//216 511//216 512//216 500//216
+f 500//215 512//215 513//215 501//215
+f 501//214 513//214 514//214 502//214
+f 502//213 514//213 515//213 503//213
+f 503//212 515//212 516//212 504//212
+f 504//211 516//211 505//211 493//211
+f 505//222 517//222 518//222 506//222
+f 506//221 518//221 519//221 507//221
+f 507//220 519//220 520//220 508//220
+f 508//219 520//219 521//219 509//219
+f 509//218 521//218 522//218 510//218
+f 510//217 522//217 523//217 511//217
+f 511//228 523//228 524//228 512//228
+f 512//227 524//227 525//227 513//227
+f 513//226 525//226 526//226 514//226
+f 514//225 526//225 527//225 515//225
+f 515//224 527//224 528//224 516//224
+f 516//223 528//223 517//223 505//223
+f 517//234 529//234 530//234 518//234
+f 518//233 530//233 531//233 519//233
+f 519//232 531//232 532//232 520//232
+f 520//231 532//231 533//231 521//231
+f 521//230 533//230 534//230 522//230
+f 522//229 534//229 535//229 523//229
+f 523//240 535//240 536//240 524//240
+f 524//239 536//239 537//239 525//239
+f 525//238 537//238 538//238 526//238
+f 526//237 538//237 539//237 527//237
+f 527//236 539//236 540//236 528//236
+f 528//235 540//235 529//235 517//235
+f 529//246 541//246 542//246 530//246
+f 530//245 542//245 543//245 531//245
+f 531//244 543//244 544//244 532//244
+f 532//243 544//243 545//243 533//243
+f 533//242 545//242 546//242 534//242
+f 534//241 546//241 547//241 535//241
+f 535//252 547//252 548//252 536//252
+f 536//251 548//251 549//251 537//251
+f 537//250 549//250 550//250 538//250
+f 538//249 550//249 551//249 539//249
+f 539//248 551//248 552//248 540//248
+f 540//247 552//247 541//247 529//247
+f 541//258 553//258 554//258 542//258
+f 542//257 554//257 555//257 543//257
+f 543//256 555//256 556//256 544//256
+f 544//255 556//255 557//255 545//255
+f 545//254 557//254 558//254 546//254
+f 546//253 558//253 559//253 547//253
+f 547//264 559//264 560//264 548//264
+f 548//263 560//263 561//263 549//263
+f 549//262 561//262 562//262 550//262
+f 550//261 562//261 563//261 551//261
+f 551//260 563//260 564//260 552//260
+f 552//259 564//259 553//259 541//259
+f 553//270 565//270 566//270 554//270
+f 554//269 566//269 567//269 555//269
+f 555//268 567//268 568//268 556//268
+f 556//267 568//267 569//267 557//267
+f 557//266 569//266 570//266 558//266
+f 558//265 570//265 571//265 559//265
+f 559//276 571//276 572//276 560//276
+f 560//275 572//275 573//275 561//275
+f 561//274 573//274 574//274 562//274
+f 562//273 574//273 575//273 563//273
+f 563//272 575//272 576//272 564//272
+f 564//271 576//271 565//271 553//271
+f 565//282 1//282 2//282 566//282
+f 566//281 2//281 3//281 567//281
+f 567//280 3//280 4//280 568//280
+f 568//279 4//279 5//279 569//279
+f 569//278 5//278 6//278 570//278
+f 570//277 6//277 7//277 571//277
+f 571//288 7//288 8//288 572//288
+f 572//287 8//287 9//287 573//287
+f 573//286 9//286 10//286 574//286
+f 574//285 10//285 11//285 575//285
+f 575//284 11//284 12//284 576//284
+f 576//283 12//283 1//283 565//283
diff --git a/data/torus/torus.urdf b/data/torus/torus.urdf
new file mode 100644
index 000000000..57dc51c06
--- /dev/null
+++ b/data/torus/torus.urdf
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/torus/torus_only.mtl b/data/torus/torus_only.mtl
new file mode 100644
index 000000000..5361e19b8
--- /dev/null
+++ b/data/torus/torus_only.mtl
@@ -0,0 +1,12 @@
+# Blender MTL File: 'None'
+# Material Count: 1
+
+newmtl None
+Ns 0.000000
+Ka 0.000000 0.000000 0.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.800000 0.800000 0.800000
+Ke 0.000000 0.000000 0.000000
+Ni 1.000000
+d 1.000000
+illum 2
diff --git a/data/torus/torus_only.obj b/data/torus/torus_only.obj
new file mode 100644
index 000000000..a6776c93e
--- /dev/null
+++ b/data/torus/torus_only.obj
@@ -0,0 +1,1474 @@
+# Blender v2.77 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib torus_only.mtl
+o Torus
+v 1.269537 0.006289 1.359776
+v 1.258843 0.006289 1.196618
+v 1.225636 0.131289 1.200990
+v 1.236043 0.131289 1.359776
+v 1.134912 0.222796 1.212934
+v 1.144537 0.222796 1.359776
+v 1.010982 0.256289 1.229250
+v 1.019537 0.256289 1.359776
+v 0.887051 0.222796 1.245565
+v 0.894537 0.222796 1.359776
+v 0.796328 0.131289 1.257509
+v 0.803031 0.131289 1.359776
+v 0.763121 0.006289 1.261881
+v 0.769537 0.006289 1.359776
+v 0.796328 -0.118711 1.257509
+v 0.803031 -0.118711 1.359776
+v 0.887051 -0.210217 1.245565
+v 0.894537 -0.210217 1.359776
+v 1.010982 -0.243711 1.229250
+v 1.019537 -0.243711 1.359776
+v 1.134912 -0.210217 1.212934
+v 1.144537 -0.210217 1.359776
+v 1.225636 -0.118711 1.200990
+v 1.236043 -0.118711 1.359776
+v 1.226944 0.006289 1.036252
+v 1.194592 0.131289 1.044921
+v 1.106204 0.222796 1.068604
+v 0.985463 0.256289 1.100957
+v 0.864722 0.222796 1.133309
+v 0.776334 0.131289 1.156993
+v 0.743981 0.006289 1.165661
+v 0.776334 -0.118711 1.156993
+v 0.864722 -0.210217 1.133309
+v 0.985463 -0.243711 1.100957
+v 1.106204 -0.210217 1.068604
+v 1.194592 -0.118711 1.044921
+v 1.174387 0.006289 0.881421
+v 1.143442 0.131289 0.894239
+v 1.058902 0.222796 0.929257
+v 0.943417 0.256289 0.977092
+v 0.827932 0.222796 1.024928
+v 0.743391 0.131289 1.059946
+v 0.712447 0.006289 1.072763
+v 0.743391 -0.118711 1.059946
+v 0.827932 -0.210217 1.024928
+v 0.943417 -0.243711 0.977092
+v 1.058902 -0.210217 0.929257
+v 1.143442 -0.118711 0.894239
+v 1.102069 0.006289 0.734776
+v 1.073062 0.131289 0.751522
+v 0.993815 0.222796 0.797276
+v 0.885562 0.256289 0.859776
+v 0.777309 0.222796 0.922276
+v 0.698062 0.131289 0.968029
+v 0.669056 0.006289 0.984776
+v 0.698062 -0.118711 0.968029
+v 0.777309 -0.210217 0.922276
+v 0.885562 -0.243711 0.859776
+v 0.993815 -0.210217 0.797276
+v 1.073062 -0.118711 0.751522
+v 1.011229 0.006289 0.598824
+v 0.984656 0.131289 0.619214
+v 0.912059 0.222796 0.674919
+v 0.812890 0.256289 0.751014
+v 0.713721 0.222796 0.827109
+v 0.641124 0.131289 0.882815
+v 0.614552 0.006289 0.903205
+v 0.641124 -0.118711 0.882815
+v 0.713721 -0.210217 0.827109
+v 0.812890 -0.243711 0.751014
+v 0.912059 -0.210217 0.674919
+v 0.984656 -0.118711 0.619214
+v 0.903420 0.006289 0.475892
+v 0.879737 0.131289 0.499576
+v 0.815032 0.222796 0.564281
+v 0.726644 0.256289 0.652669
+v 0.638255 0.222796 0.741057
+v 0.573551 0.131289 0.805762
+v 0.549867 0.006289 0.829446
+v 0.573551 -0.118711 0.805762
+v 0.638255 -0.210217 0.741057
+v 0.726644 -0.243711 0.652669
+v 0.815032 -0.210217 0.564281
+v 0.879737 -0.118711 0.499576
+v 0.780489 0.006289 0.368084
+v 0.760099 0.131289 0.394656
+v 0.704394 0.222796 0.467253
+v 0.628298 0.256289 0.566423
+v 0.552203 0.222796 0.665592
+v 0.496498 0.131289 0.738188
+v 0.476108 0.006289 0.764761
+v 0.496498 -0.118711 0.738188
+v 0.552203 -0.210217 0.665592
+v 0.628298 -0.243711 0.566423
+v 0.704394 -0.210217 0.467253
+v 0.760099 -0.118711 0.394656
+v 0.644537 0.006289 0.277244
+v 0.627790 0.131289 0.306250
+v 0.582037 0.222796 0.385497
+v 0.519537 0.256289 0.493750
+v 0.457037 0.222796 0.602003
+v 0.411284 0.131289 0.681250
+v 0.394537 0.006289 0.710257
+v 0.411284 -0.118711 0.681250
+v 0.457037 -0.210217 0.602003
+v 0.519537 -0.243711 0.493750
+v 0.582037 -0.210217 0.385497
+v 0.627790 -0.118711 0.306250
+v 0.497891 0.006289 0.204926
+v 0.485074 0.131289 0.235871
+v 0.450056 0.222796 0.320411
+v 0.402221 0.256289 0.435896
+v 0.354385 0.222796 0.551381
+v 0.319367 0.131289 0.635922
+v 0.306550 0.006289 0.666866
+v 0.319367 -0.118711 0.635922
+v 0.354385 -0.210217 0.551381
+v 0.402221 -0.243711 0.435896
+v 0.450056 -0.210217 0.320411
+v 0.485074 -0.118711 0.235871
+v 0.343061 0.006289 0.152368
+v 0.334392 0.131289 0.184721
+v 0.310708 0.222796 0.273109
+v 0.278356 0.256289 0.393850
+v 0.246004 0.222796 0.514591
+v 0.222320 0.131289 0.602979
+v 0.213651 0.006289 0.635331
+v 0.222320 -0.118711 0.602979
+v 0.246004 -0.210217 0.514591
+v 0.278356 -0.243711 0.393850
+v 0.310708 -0.210217 0.273109
+v 0.334392 -0.118711 0.184721
+v 0.182694 0.006289 0.120470
+v 0.178323 0.131289 0.153677
+v 0.166379 0.222796 0.244400
+v 0.150063 0.256289 0.368331
+v 0.133747 0.222796 0.492261
+v 0.121803 0.131289 0.582985
+v 0.117431 0.006289 0.616192
+v 0.121803 -0.118711 0.582985
+v 0.133747 -0.210217 0.492261
+v 0.150063 -0.243711 0.368331
+v 0.166379 -0.210217 0.244400
+v 0.178323 -0.118711 0.153677
+v 0.019537 0.006289 0.109776
+v 0.019537 0.131289 0.143269
+v 0.019537 0.222796 0.234776
+v 0.019537 0.256289 0.359776
+v 0.019537 0.222796 0.484776
+v 0.019537 0.131289 0.576282
+v 0.019537 0.006289 0.609776
+v 0.019537 -0.118711 0.576282
+v 0.019537 -0.210217 0.484776
+v 0.019537 -0.243711 0.359776
+v 0.019537 -0.210217 0.234776
+v 0.019537 -0.118711 0.143269
+v -0.143621 0.006289 0.120470
+v -0.139249 0.131289 0.153677
+v -0.127305 0.222796 0.244400
+v -0.110989 0.256289 0.368331
+v -0.094674 0.222796 0.492261
+v -0.082730 0.131289 0.582985
+v -0.078358 0.006289 0.616192
+v -0.082730 -0.118711 0.582985
+v -0.094674 -0.210217 0.492261
+v -0.110989 -0.243711 0.368331
+v -0.127305 -0.210217 0.244400
+v -0.139249 -0.118711 0.153677
+v -0.303987 0.006289 0.152368
+v -0.295318 0.131289 0.184721
+v -0.271634 0.222796 0.273109
+v -0.239282 0.256289 0.393850
+v -0.206930 0.222796 0.514590
+v -0.183246 0.131289 0.602979
+v -0.174577 0.006289 0.635331
+v -0.183246 -0.118711 0.602979
+v -0.206930 -0.210217 0.514590
+v -0.239282 -0.243711 0.393850
+v -0.271634 -0.210217 0.273109
+v -0.295318 -0.118711 0.184721
+v -0.458818 0.006289 0.204926
+v -0.446000 0.131289 0.235870
+v -0.410982 0.222796 0.320411
+v -0.363147 0.256289 0.435896
+v -0.315311 0.222796 0.551381
+v -0.280293 0.131289 0.635922
+v -0.267476 0.006289 0.666866
+v -0.280293 -0.118711 0.635922
+v -0.315311 -0.210217 0.551381
+v -0.363147 -0.243711 0.435896
+v -0.410982 -0.210217 0.320411
+v -0.446000 -0.118711 0.235870
+v -0.605463 0.006289 0.277244
+v -0.588716 0.131289 0.306250
+v -0.542963 0.222796 0.385497
+v -0.480463 0.256289 0.493750
+v -0.417963 0.222796 0.602003
+v -0.372210 0.131289 0.681250
+v -0.355463 0.006289 0.710257
+v -0.372210 -0.118711 0.681250
+v -0.417963 -0.210217 0.602003
+v -0.480463 -0.243711 0.493750
+v -0.542963 -0.210217 0.385497
+v -0.588716 -0.118711 0.306250
+v -0.741415 0.006289 0.368084
+v -0.721025 0.131289 0.394656
+v -0.665320 0.222796 0.467253
+v -0.589225 0.256289 0.566422
+v -0.513129 0.222796 0.665592
+v -0.457424 0.131289 0.738188
+v -0.437034 0.006289 0.764761
+v -0.457424 -0.118711 0.738188
+v -0.513129 -0.210217 0.665592
+v -0.589225 -0.243711 0.566422
+v -0.665320 -0.210217 0.467253
+v -0.721025 -0.118711 0.394656
+v -0.864347 0.006289 0.475893
+v -0.840663 0.131289 0.499576
+v -0.775958 0.222796 0.564281
+v -0.687570 0.256289 0.652669
+v -0.599182 0.222796 0.741057
+v -0.534477 0.131289 0.805762
+v -0.510793 0.006289 0.829446
+v -0.534477 -0.118711 0.805762
+v -0.599182 -0.210217 0.741057
+v -0.687570 -0.243711 0.652669
+v -0.775958 -0.210217 0.564281
+v -0.840663 -0.118711 0.499576
+v -0.972155 0.006289 0.598824
+v -0.945583 0.131289 0.619214
+v -0.872986 0.222796 0.674919
+v -0.773816 0.256289 0.751014
+v -0.674647 0.222796 0.827109
+v -0.602050 0.131289 0.882815
+v -0.575478 0.006289 0.903205
+v -0.602050 -0.118711 0.882815
+v -0.674647 -0.210217 0.827109
+v -0.773816 -0.243711 0.751014
+v -0.872986 -0.210217 0.674919
+v -0.945583 -0.118711 0.619214
+v -1.062995 0.006289 0.734775
+v -1.033988 0.131289 0.751522
+v -0.954742 0.222796 0.797275
+v -0.846488 0.256289 0.859775
+v -0.738235 0.222796 0.922275
+v -0.658988 0.131289 0.968029
+v -0.629982 0.006289 0.984775
+v -0.658988 -0.118711 0.968029
+v -0.738235 -0.210217 0.922275
+v -0.846488 -0.243711 0.859775
+v -0.954742 -0.210217 0.797275
+v -1.033988 -0.118711 0.751522
+v -1.135312 0.006289 0.881421
+v -1.104368 0.131289 0.894239
+v -1.019827 0.222796 0.929257
+v -0.904343 0.256289 0.977092
+v -0.788858 0.222796 1.024928
+v -0.704317 0.131289 1.059946
+v -0.673373 0.006289 1.072763
+v -0.704317 -0.118711 1.059946
+v -0.788858 -0.210217 1.024928
+v -0.904343 -0.243711 0.977092
+v -1.019827 -0.210217 0.929257
+v -1.104368 -0.118711 0.894239
+v -1.187871 0.006289 1.036252
+v -1.155518 0.131289 1.044921
+v -1.067130 0.222796 1.068604
+v -0.946389 0.256289 1.100957
+v -0.825648 0.222796 1.133309
+v -0.737260 0.131289 1.156993
+v -0.704908 0.006289 1.165662
+v -0.737260 -0.118711 1.156993
+v -0.825648 -0.210217 1.133309
+v -0.946389 -0.243711 1.100957
+v -1.067130 -0.210217 1.068604
+v -1.155518 -0.118711 1.044921
+v -1.219769 0.006289 1.196618
+v -1.186562 0.131289 1.200990
+v -1.095839 0.222796 1.212934
+v -0.971908 0.256289 1.229249
+v -0.847977 0.222796 1.245565
+v -0.757254 0.131289 1.257509
+v -0.724047 0.006289 1.261881
+v -0.757254 -0.118711 1.257509
+v -0.847977 -0.210217 1.245565
+v -0.971908 -0.243711 1.229249
+v -1.095839 -0.210217 1.212934
+v -1.186562 -0.118711 1.200990
+v -1.230463 0.006289 1.359776
+v -1.196970 0.131289 1.359776
+v -1.105463 0.222796 1.359776
+v -0.980463 0.256289 1.359776
+v -0.855463 0.222796 1.359776
+v -0.763957 0.131289 1.359776
+v -0.730463 0.006289 1.359776
+v -0.763957 -0.118711 1.359776
+v -0.855463 -0.210217 1.359776
+v -0.980463 -0.243711 1.359776
+v -1.105463 -0.210217 1.359776
+v -1.196970 -0.118711 1.359776
+v -1.219769 0.006289 1.522934
+v -1.186562 0.131289 1.518562
+v -1.095839 0.222796 1.506618
+v -0.971908 0.256289 1.490302
+v -0.847977 0.222796 1.473986
+v -0.757254 0.131289 1.462042
+v -0.724047 0.006289 1.457670
+v -0.757254 -0.118711 1.462042
+v -0.847977 -0.210217 1.473986
+v -0.971908 -0.243711 1.490302
+v -1.095839 -0.210217 1.506618
+v -1.186562 -0.118711 1.518562
+v -1.187871 0.006289 1.683299
+v -1.155518 0.131289 1.674631
+v -1.067130 0.222796 1.650947
+v -0.946389 0.256289 1.618595
+v -0.825648 0.222796 1.586242
+v -0.737260 0.131289 1.562559
+v -0.704908 0.006289 1.553890
+v -0.737260 -0.118711 1.562559
+v -0.825648 -0.210217 1.586242
+v -0.946389 -0.243711 1.618595
+v -1.067130 -0.210217 1.650947
+v -1.155518 -0.118711 1.674631
+v -1.135313 0.006289 1.838130
+v -1.104369 0.131289 1.825312
+v -1.019828 0.222796 1.790294
+v -0.904343 0.256289 1.742459
+v -0.788858 0.222796 1.694623
+v -0.704317 0.131289 1.659605
+v -0.673373 0.006289 1.646788
+v -0.704317 -0.118711 1.659605
+v -0.788858 -0.210217 1.694623
+v -0.904343 -0.243711 1.742459
+v -1.019828 -0.210217 1.790294
+v -1.104369 -0.118711 1.825312
+v -1.062995 0.006289 1.984776
+v -1.033989 0.131289 1.968029
+v -0.954742 0.222796 1.922276
+v -0.846489 0.256289 1.859776
+v -0.738235 0.222796 1.797276
+v -0.658989 0.131289 1.751522
+v -0.629982 0.006289 1.734776
+v -0.658989 -0.118711 1.751522
+v -0.738235 -0.210217 1.797276
+v -0.846489 -0.243711 1.859776
+v -0.954742 -0.210217 1.922276
+v -1.033989 -0.118711 1.968029
+v -0.972155 0.006289 2.120728
+v -0.945583 0.131289 2.100338
+v -0.872986 0.222796 2.044632
+v -0.773816 0.256289 1.968537
+v -0.674647 0.222796 1.892442
+v -0.602050 0.131289 1.836736
+v -0.575478 0.006289 1.816347
+v -0.602050 -0.118711 1.836736
+v -0.674647 -0.210217 1.892442
+v -0.773816 -0.243711 1.968537
+v -0.872986 -0.210217 2.044632
+v -0.945583 -0.118711 2.100338
+v -0.864347 0.006289 2.243659
+v -0.840663 0.131289 2.219975
+v -0.775958 0.222796 2.155271
+v -0.687570 0.256289 2.066882
+v -0.599182 0.222796 1.978494
+v -0.534477 0.131289 1.913789
+v -0.510793 0.006289 1.890106
+v -0.534477 -0.118711 1.913789
+v -0.599182 -0.210217 1.978494
+v -0.687570 -0.243711 2.066882
+v -0.775958 -0.210217 2.155271
+v -0.840663 -0.118711 2.219975
+v -0.741416 0.006289 2.351467
+v -0.721026 0.131289 2.324895
+v -0.665320 0.222796 2.252298
+v -0.589225 0.256289 2.153129
+v -0.513130 0.222796 2.053960
+v -0.457424 0.131289 1.981363
+v -0.437034 0.006289 1.954791
+v -0.457424 -0.118711 1.981363
+v -0.513130 -0.210217 2.053960
+v -0.589225 -0.243711 2.153129
+v -0.665320 -0.210217 2.252298
+v -0.721026 -0.118711 2.324895
+v -0.605463 0.006289 2.442308
+v -0.588716 0.131289 2.413301
+v -0.542963 0.222796 2.334054
+v -0.480463 0.256289 2.225801
+v -0.417963 0.222796 2.117548
+v -0.372210 0.131289 2.038301
+v -0.355463 0.006289 2.009295
+v -0.372210 -0.118711 2.038301
+v -0.417963 -0.210217 2.117548
+v -0.480463 -0.243711 2.225801
+v -0.542963 -0.210217 2.334054
+v -0.588716 -0.118711 2.413301
+v -0.458818 0.006289 2.514625
+v -0.446000 0.131289 2.483681
+v -0.410982 0.222796 2.399140
+v -0.363147 0.256289 2.283655
+v -0.315311 0.222796 2.168170
+v -0.280293 0.131289 2.083629
+v -0.267476 0.006289 2.052685
+v -0.280293 -0.118711 2.083629
+v -0.315311 -0.210217 2.168170
+v -0.363147 -0.243711 2.283655
+v -0.410982 -0.210217 2.399140
+v -0.446000 -0.118711 2.483681
+v -0.303987 0.006289 2.567183
+v -0.295318 0.131289 2.534830
+v -0.271635 0.222796 2.446442
+v -0.239282 0.256289 2.325701
+v -0.206930 0.222796 2.204961
+v -0.183246 0.131289 2.116572
+v -0.174578 0.006289 2.084220
+v -0.183246 -0.118711 2.116572
+v -0.206930 -0.210217 2.204961
+v -0.239282 -0.243711 2.325701
+v -0.271635 -0.210217 2.446442
+v -0.295318 -0.118711 2.534830
+v -0.143622 0.006289 2.599082
+v -0.139250 0.131289 2.565874
+v -0.127306 0.222796 2.475151
+v -0.110990 0.256289 2.351220
+v -0.094674 0.222796 2.227290
+v -0.082730 0.131289 2.136566
+v -0.078358 0.006289 2.103359
+v -0.082730 -0.118711 2.136566
+v -0.094674 -0.210217 2.227290
+v -0.110990 -0.243711 2.351220
+v -0.127306 -0.210217 2.475151
+v -0.139250 -0.118711 2.565874
+v 0.019537 0.006289 2.609776
+v 0.019537 0.131289 2.576282
+v 0.019537 0.222796 2.484776
+v 0.019537 0.256289 2.359776
+v 0.019537 0.222796 2.234776
+v 0.019537 0.131289 2.143269
+v 0.019537 0.006289 2.109776
+v 0.019537 -0.118711 2.143269
+v 0.019537 -0.210217 2.234776
+v 0.019537 -0.243711 2.359776
+v 0.019537 -0.210217 2.484776
+v 0.019537 -0.118711 2.576282
+v 0.182694 0.006289 2.599082
+v 0.178323 0.131289 2.565875
+v 0.166379 0.222796 2.475151
+v 0.150063 0.256289 2.351221
+v 0.133747 0.222796 2.227290
+v 0.121803 0.131289 2.136566
+v 0.117431 0.006289 2.103359
+v 0.121803 -0.118711 2.136566
+v 0.133747 -0.210217 2.227290
+v 0.150063 -0.243711 2.351221
+v 0.166379 -0.210217 2.475151
+v 0.178323 -0.118711 2.565875
+v 0.343060 0.006289 2.567183
+v 0.334391 0.131289 2.534831
+v 0.310708 0.222796 2.446442
+v 0.278356 0.256289 2.325702
+v 0.246003 0.222796 2.204961
+v 0.222320 0.131289 2.116573
+v 0.213651 0.006289 2.084220
+v 0.222320 -0.118711 2.116573
+v 0.246003 -0.210217 2.204961
+v 0.278356 -0.243711 2.325702
+v 0.310708 -0.210217 2.446442
+v 0.334391 -0.118711 2.534831
+v 0.497891 0.006289 2.514625
+v 0.485074 0.131289 2.483681
+v 0.450056 0.222796 2.399140
+v 0.402221 0.256289 2.283655
+v 0.354385 0.222796 2.168170
+v 0.319367 0.131289 2.083629
+v 0.306550 0.006289 2.052685
+v 0.319367 -0.118711 2.083629
+v 0.354385 -0.210217 2.168170
+v 0.402221 -0.243711 2.283655
+v 0.450056 -0.210217 2.399140
+v 0.485074 -0.118711 2.483681
+v 0.644537 0.006289 2.442307
+v 0.627790 0.131289 2.413301
+v 0.582037 0.222796 2.334054
+v 0.519537 0.256289 2.225801
+v 0.457037 0.222796 2.117548
+v 0.411284 0.131289 2.038301
+v 0.394537 0.006289 2.009295
+v 0.411284 -0.118711 2.038301
+v 0.457037 -0.210217 2.117548
+v 0.519537 -0.243711 2.225801
+v 0.582037 -0.210217 2.334054
+v 0.627790 -0.118711 2.413301
+v 0.780488 0.006289 2.351468
+v 0.760099 0.131289 2.324895
+v 0.704393 0.222796 2.252298
+v 0.628298 0.256289 2.153129
+v 0.552203 0.222796 2.053960
+v 0.496497 0.131289 1.981363
+v 0.476108 0.006289 1.954791
+v 0.496497 -0.118711 1.981363
+v 0.552203 -0.210217 2.053960
+v 0.628298 -0.243711 2.153129
+v 0.704393 -0.210217 2.252298
+v 0.760099 -0.118711 2.324895
+v 0.903420 0.006289 2.243660
+v 0.879736 0.131289 2.219976
+v 0.815032 0.222796 2.155271
+v 0.726643 0.256289 2.066883
+v 0.638255 0.222796 1.978495
+v 0.573550 0.131289 1.913790
+v 0.549867 0.006289 1.890106
+v 0.573550 -0.118711 1.913790
+v 0.638255 -0.210217 1.978495
+v 0.726643 -0.243711 2.066883
+v 0.815032 -0.210217 2.155271
+v 0.879736 -0.118711 2.219976
+v 1.011229 0.006289 2.120727
+v 0.984656 0.131289 2.100338
+v 0.912059 0.222796 2.044632
+v 0.812890 0.256289 1.968537
+v 0.713721 0.222796 1.892442
+v 0.641124 0.131289 1.836736
+v 0.614552 0.006289 1.816347
+v 0.641124 -0.118711 1.836736
+v 0.713721 -0.210217 1.892442
+v 0.812890 -0.243711 1.968537
+v 0.912059 -0.210217 2.044632
+v 0.984656 -0.118711 2.100338
+v 1.102069 0.006289 1.984776
+v 1.073062 0.131289 1.968029
+v 0.993815 0.222796 1.922276
+v 0.885562 0.256289 1.859776
+v 0.777309 0.222796 1.797276
+v 0.698062 0.131289 1.751523
+v 0.669056 0.006289 1.734776
+v 0.698062 -0.118711 1.751523
+v 0.777309 -0.210217 1.797276
+v 0.885562 -0.243711 1.859776
+v 0.993815 -0.210217 1.922276
+v 1.073062 -0.118711 1.968029
+v 1.174386 0.006289 1.838130
+v 1.143442 0.131289 1.825313
+v 1.058901 0.222796 1.790295
+v 0.943416 0.256289 1.742460
+v 0.827931 0.222796 1.694624
+v 0.743391 0.131289 1.659606
+v 0.712446 0.006289 1.646789
+v 0.743391 -0.118711 1.659606
+v 0.827931 -0.210217 1.694624
+v 0.943416 -0.243711 1.742460
+v 1.058901 -0.210217 1.790295
+v 1.143442 -0.118711 1.825313
+v 1.226944 0.006289 1.683299
+v 1.194592 0.131289 1.674630
+v 1.106204 0.222796 1.650947
+v 0.985463 0.256289 1.618594
+v 0.864722 0.222796 1.586242
+v 0.776334 0.131289 1.562559
+v 0.743981 0.006289 1.553890
+v 0.776334 -0.118711 1.562559
+v 0.864722 -0.210217 1.586242
+v 0.985463 -0.243711 1.618594
+v 1.106204 -0.210217 1.650947
+v 1.194592 -0.118711 1.674630
+v 1.258843 0.006289 1.522933
+v 1.225636 0.131289 1.518562
+v 1.134912 0.222796 1.506618
+v 1.010982 0.256289 1.490302
+v 0.887051 0.222796 1.473986
+v 0.796328 0.131289 1.462042
+v 0.763121 0.006289 1.457670
+v 0.796328 -0.118711 1.462042
+v 0.887051 -0.210217 1.473986
+v 1.010982 -0.243711 1.490302
+v 1.134912 -0.210217 1.506618
+v 1.225636 -0.118711 1.518562
+vn 0.9640 0.2583 -0.0632
+vn 0.7064 0.7063 -0.0463
+vn 0.2588 0.9658 -0.0170
+vn -0.2588 0.9658 0.0170
+vn -0.7064 0.7063 0.0463
+vn -0.9640 0.2583 0.0632
+vn -0.9640 -0.2583 0.0632
+vn -0.7063 -0.7063 0.0463
+vn -0.2588 -0.9658 0.0170
+vn 0.2588 -0.9658 -0.0170
+vn 0.7063 -0.7064 -0.0463
+vn 0.9640 -0.2583 -0.0632
+vn 0.9475 0.2583 -0.1885
+vn 0.6943 0.7063 -0.1381
+vn 0.2543 0.9658 -0.0506
+vn -0.2543 0.9658 0.0506
+vn -0.6943 0.7063 0.1381
+vn -0.9475 0.2583 0.1885
+vn -0.9475 -0.2583 0.1885
+vn -0.6943 -0.7063 0.1381
+vn -0.2544 -0.9658 0.0506
+vn 0.2544 -0.9658 -0.0506
+vn 0.6943 -0.7063 -0.1381
+vn 0.9475 -0.2583 -0.1885
+vn 0.9148 0.2583 -0.3105
+vn 0.6703 0.7063 -0.2275
+vn 0.2456 0.9658 -0.0834
+vn -0.2456 0.9658 0.0834
+vn -0.6703 0.7063 0.2275
+vn -0.9148 0.2583 0.3105
+vn -0.9148 -0.2583 0.3105
+vn -0.6703 -0.7064 0.2275
+vn -0.2456 -0.9658 0.0834
+vn 0.2456 -0.9658 -0.0834
+vn 0.6703 -0.7063 -0.2275
+vn 0.9148 -0.2583 -0.3105
+vn 0.8664 0.2583 -0.4273
+vn 0.6349 0.7063 -0.3131
+vn 0.2326 0.9658 -0.1147
+vn -0.2326 0.9658 0.1147
+vn -0.6349 0.7063 0.3131
+vn -0.8664 0.2583 0.4273
+vn -0.8664 -0.2583 0.4273
+vn -0.6349 -0.7064 0.3131
+vn -0.2326 -0.9658 0.1147
+vn 0.2326 -0.9658 -0.1147
+vn 0.6349 -0.7064 -0.3131
+vn 0.8664 -0.2583 -0.4273
+vn 0.8033 0.2583 -0.5367
+vn 0.5886 0.7063 -0.3933
+vn 0.2156 0.9658 -0.1441
+vn -0.2156 0.9658 0.1441
+vn -0.5886 0.7063 0.3933
+vn -0.8033 0.2583 0.5367
+vn -0.8033 -0.2583 0.5367
+vn -0.5886 -0.7064 0.3933
+vn -0.2156 -0.9658 0.1441
+vn 0.2156 -0.9658 -0.1441
+vn 0.5886 -0.7063 -0.3933
+vn 0.8033 -0.2583 -0.5367
+vn 0.7263 0.2583 -0.6370
+vn 0.5322 0.7063 -0.4667
+vn 0.1950 0.9658 -0.1710
+vn -0.1950 0.9658 0.1710
+vn -0.5322 0.7063 0.4667
+vn -0.7263 0.2583 0.6370
+vn -0.7263 -0.2583 0.6370
+vn -0.5322 -0.7064 0.4667
+vn -0.1950 -0.9658 0.1710
+vn 0.1950 -0.9658 -0.1710
+vn 0.5322 -0.7063 -0.4667
+vn 0.7263 -0.2583 -0.6370
+vn 0.6370 0.2583 -0.7263
+vn 0.4667 0.7063 -0.5322
+vn 0.1710 0.9658 -0.1950
+vn -0.1710 0.9658 0.1950
+vn -0.4667 0.7063 0.5322
+vn -0.6370 0.2583 0.7263
+vn -0.6370 -0.2583 0.7263
+vn -0.4667 -0.7063 0.5322
+vn -0.1710 -0.9658 0.1950
+vn 0.1710 -0.9658 -0.1950
+vn 0.4667 -0.7064 -0.5322
+vn 0.6370 -0.2583 -0.7263
+vn 0.5367 0.2583 -0.8033
+vn 0.3933 0.7063 -0.5886
+vn 0.1441 0.9658 -0.2156
+vn -0.1441 0.9658 0.2156
+vn -0.3933 0.7063 0.5886
+vn -0.5367 0.2583 0.8033
+vn -0.5367 -0.2583 0.8033
+vn -0.3933 -0.7063 0.5886
+vn -0.1441 -0.9658 0.2156
+vn 0.1441 -0.9658 -0.2156
+vn 0.3933 -0.7063 -0.5886
+vn 0.5367 -0.2583 -0.8033
+vn 0.4273 0.2583 -0.8664
+vn 0.3131 0.7063 -0.6349
+vn 0.1147 0.9658 -0.2326
+vn -0.1147 0.9658 0.2326
+vn -0.3131 0.7063 0.6349
+vn -0.4273 0.2583 0.8664
+vn -0.4273 -0.2583 0.8664
+vn -0.3131 -0.7064 0.6349
+vn -0.1147 -0.9658 0.2326
+vn 0.1147 -0.9658 -0.2326
+vn 0.3131 -0.7063 -0.6349
+vn 0.4273 -0.2583 -0.8664
+vn 0.3105 0.2583 -0.9148
+vn 0.2275 0.7063 -0.6703
+vn 0.0834 0.9658 -0.2456
+vn -0.0834 0.9658 0.2456
+vn -0.2275 0.7063 0.6703
+vn -0.3105 0.2583 0.9148
+vn -0.3105 -0.2583 0.9148
+vn -0.2275 -0.7064 0.6703
+vn -0.0834 -0.9658 0.2456
+vn 0.0834 -0.9658 -0.2456
+vn 0.2275 -0.7063 -0.6703
+vn 0.3105 -0.2583 -0.9148
+vn 0.1885 0.2583 -0.9475
+vn 0.1381 0.7063 -0.6943
+vn 0.0506 0.9658 -0.2543
+vn -0.0506 0.9658 0.2543
+vn -0.1381 0.7063 0.6943
+vn -0.1885 0.2583 0.9475
+vn -0.1885 -0.2583 0.9475
+vn -0.1381 -0.7064 0.6943
+vn -0.0506 -0.9658 0.2544
+vn 0.0506 -0.9658 -0.2544
+vn 0.1381 -0.7063 -0.6943
+vn 0.1885 -0.2583 -0.9475
+vn 0.0632 0.2583 -0.9640
+vn 0.0463 0.7063 -0.7064
+vn 0.0170 0.9658 -0.2588
+vn -0.0170 0.9658 0.2588
+vn -0.0463 0.7063 0.7064
+vn -0.0632 0.2583 0.9640
+vn -0.0632 -0.2583 0.9640
+vn -0.0463 -0.7064 0.7063
+vn -0.0170 -0.9658 0.2588
+vn 0.0170 -0.9658 -0.2588
+vn 0.0463 -0.7064 -0.7063
+vn 0.0632 -0.2583 -0.9640
+vn -0.0632 0.2583 -0.9640
+vn -0.0463 0.7063 -0.7064
+vn -0.0170 0.9658 -0.2588
+vn 0.0170 0.9658 0.2588
+vn 0.0463 0.7063 0.7064
+vn 0.0632 0.2583 0.9640
+vn 0.0632 -0.2583 0.9640
+vn 0.0463 -0.7064 0.7063
+vn 0.0170 -0.9658 0.2588
+vn -0.0170 -0.9658 -0.2588
+vn -0.0463 -0.7064 -0.7063
+vn -0.0632 -0.2583 -0.9640
+vn -0.1885 0.2583 -0.9475
+vn -0.1381 0.7063 -0.6943
+vn -0.0506 0.9658 -0.2543
+vn 0.0506 0.9658 0.2544
+vn 0.1381 0.7063 0.6943
+vn 0.1885 0.2583 0.9475
+vn 0.1885 -0.2583 0.9475
+vn 0.1381 -0.7064 0.6943
+vn 0.0506 -0.9658 0.2544
+vn -0.0506 -0.9658 -0.2544
+vn -0.1381 -0.7063 -0.6943
+vn -0.1885 -0.2583 -0.9475
+vn -0.3105 0.2583 -0.9148
+vn -0.2275 0.7063 -0.6703
+vn -0.0834 0.9658 -0.2456
+vn 0.0834 0.9658 0.2456
+vn 0.2275 0.7063 0.6703
+vn 0.3105 0.2583 0.9148
+vn 0.3105 -0.2583 0.9148
+vn 0.2275 -0.7064 0.6703
+vn 0.0834 -0.9658 0.2456
+vn -0.0834 -0.9658 -0.2456
+vn -0.2275 -0.7063 -0.6703
+vn -0.3105 -0.2583 -0.9148
+vn -0.4273 0.2583 -0.8664
+vn -0.3131 0.7063 -0.6349
+vn -0.1147 0.9658 -0.2326
+vn 0.1147 0.9658 0.2326
+vn 0.3131 0.7063 0.6349
+vn 0.4273 0.2583 0.8664
+vn 0.4273 -0.2583 0.8664
+vn 0.3131 -0.7064 0.6349
+vn 0.1147 -0.9658 0.2326
+vn -0.1147 -0.9658 -0.2326
+vn -0.3131 -0.7064 -0.6349
+vn -0.4273 -0.2583 -0.8664
+vn -0.5367 0.2583 -0.8033
+vn -0.3933 0.7063 -0.5886
+vn -0.1441 0.9658 -0.2156
+vn 0.1441 0.9658 0.2156
+vn 0.3933 0.7063 0.5886
+vn 0.5367 0.2583 0.8033
+vn 0.5367 -0.2583 0.8033
+vn 0.3933 -0.7063 0.5886
+vn 0.1441 -0.9658 0.2156
+vn -0.1441 -0.9658 -0.2156
+vn -0.3933 -0.7063 -0.5886
+vn -0.5367 -0.2583 -0.8033
+vn -0.6370 0.2583 -0.7263
+vn -0.4667 0.7063 -0.5322
+vn -0.1710 0.9658 -0.1950
+vn 0.1710 0.9658 0.1950
+vn 0.4667 0.7063 0.5322
+vn 0.6370 0.2583 0.7263
+vn 0.6370 -0.2583 0.7263
+vn 0.4667 -0.7063 0.5322
+vn 0.1710 -0.9658 0.1950
+vn -0.1710 -0.9658 -0.1950
+vn -0.4667 -0.7063 -0.5322
+vn -0.6370 -0.2583 -0.7263
+vn -0.7263 0.2583 -0.6370
+vn -0.5322 0.7063 -0.4667
+vn -0.1950 0.9658 -0.1710
+vn 0.1950 0.9658 0.1710
+vn 0.5322 0.7063 0.4667
+vn 0.7263 0.2583 0.6370
+vn 0.7263 -0.2583 0.6370
+vn 0.5322 -0.7064 0.4667
+vn 0.1950 -0.9658 0.1710
+vn -0.1950 -0.9658 -0.1710
+vn -0.5322 -0.7063 -0.4667
+vn -0.7263 -0.2583 -0.6370
+vn -0.8033 0.2583 -0.5367
+vn -0.5886 0.7063 -0.3933
+vn -0.2156 0.9658 -0.1441
+vn 0.2156 0.9658 0.1441
+vn 0.5886 0.7063 0.3933
+vn 0.8033 0.2583 0.5367
+vn 0.8033 -0.2583 0.5367
+vn 0.5886 -0.7064 0.3933
+vn 0.2156 -0.9658 0.1441
+vn -0.2156 -0.9658 -0.1441
+vn -0.5886 -0.7063 -0.3933
+vn -0.8033 -0.2583 -0.5367
+vn -0.8664 0.2583 -0.4273
+vn -0.6349 0.7063 -0.3131
+vn -0.2326 0.9658 -0.1147
+vn 0.2326 0.9658 0.1147
+vn 0.6349 0.7063 0.3131
+vn 0.8664 0.2583 0.4273
+vn 0.8664 -0.2583 0.4273
+vn 0.6349 -0.7064 0.3131
+vn 0.2326 -0.9658 0.1147
+vn -0.2326 -0.9658 -0.1147
+vn -0.6349 -0.7063 -0.3131
+vn -0.8664 -0.2583 -0.4273
+vn -0.9148 0.2583 -0.3105
+vn -0.6703 0.7063 -0.2275
+vn -0.2456 0.9658 -0.0834
+vn 0.2456 0.9658 0.0834
+vn 0.6703 0.7063 0.2275
+vn 0.9148 0.2583 0.3105
+vn 0.9148 -0.2583 0.3105
+vn 0.6703 -0.7064 0.2275
+vn 0.2456 -0.9658 0.0834
+vn -0.2456 -0.9658 -0.0834
+vn -0.6703 -0.7063 -0.2275
+vn -0.9148 -0.2583 -0.3105
+vn -0.9475 0.2583 -0.1885
+vn -0.6943 0.7063 -0.1381
+vn -0.2543 0.9658 -0.0506
+vn 0.2543 0.9658 0.0506
+vn 0.6943 0.7063 0.1381
+vn 0.9475 0.2583 0.1885
+vn 0.9475 -0.2583 0.1885
+vn 0.6943 -0.7063 0.1381
+vn 0.2544 -0.9658 0.0506
+vn -0.2544 -0.9658 -0.0506
+vn -0.6943 -0.7063 -0.1381
+vn -0.9475 -0.2583 -0.1885
+vn -0.9640 0.2583 -0.0632
+vn -0.7064 0.7063 -0.0463
+vn -0.2588 0.9658 -0.0170
+vn 0.2588 0.9658 0.0170
+vn 0.7064 0.7063 0.0463
+vn 0.9640 0.2583 0.0632
+vn 0.9640 -0.2583 0.0632
+vn 0.7063 -0.7063 0.0463
+vn 0.2588 -0.9658 0.0170
+vn -0.2588 -0.9658 -0.0170
+vn -0.7063 -0.7064 -0.0463
+vn -0.9640 -0.2583 -0.0632
+vn 0.7063 -0.7063 -0.0463
+vn -0.7063 -0.7064 0.0463
+vn 0.6349 -0.7063 -0.3131
+vn 0.5886 -0.7064 -0.3933
+vn 0.5322 -0.7064 -0.4667
+vn -0.4667 -0.7064 0.5322
+vn 0.3933 -0.7064 -0.5886
+vn -0.3933 -0.7064 0.5886
+vn 0.3131 -0.7064 -0.6349
+vn 0.2275 -0.7064 -0.6703
+vn -0.2275 -0.7063 0.6703
+vn 0.0506 0.9658 -0.2544
+vn 0.1381 -0.7064 -0.6943
+vn -0.1381 -0.7063 0.6943
+vn 0.0463 0.7063 -0.7063
+vn -0.0463 -0.7063 0.7063
+vn -0.0463 0.7063 -0.7063
+vn -0.3933 -0.7064 -0.5886
+vn 0.3933 -0.7064 0.5886
+vn -0.4667 -0.7064 -0.5322
+vn 0.4667 -0.7064 0.5322
+vn -0.5322 -0.7064 -0.4667
+vn -0.5886 -0.7064 -0.3933
+vn 0.6703 -0.7063 0.2275
+vn 0.2544 0.9658 0.0506
+vn 0.6943 -0.7064 0.1381
+vn -0.7063 -0.7063 -0.0463
+vn 0.7063 -0.7064 0.0463
+usemtl None
+s 1
+f 1//1 2//1 3//1 4//1
+f 4//2 3//2 5//2 6//2
+f 6//3 5//3 7//3 8//3
+f 8//4 7//4 9//4 10//4
+f 10//5 9//5 11//5 12//5
+f 12//6 11//6 13//6 14//6
+f 14//7 13//7 15//7 16//7
+f 16//8 15//8 17//8 18//8
+f 18//9 17//9 19//9 20//9
+f 20//10 19//10 21//10 22//10
+f 22//11 21//11 23//11 24//11
+f 1//12 24//12 23//12 2//12
+f 2//13 25//13 26//13 3//13
+f 3//14 26//14 27//14 5//14
+f 5//15 27//15 28//15 7//15
+f 7//16 28//16 29//16 9//16
+f 9//17 29//17 30//17 11//17
+f 11//18 30//18 31//18 13//18
+f 13//19 31//19 32//19 15//19
+f 15//20 32//20 33//20 17//20
+f 17//21 33//21 34//21 19//21
+f 19//22 34//22 35//22 21//22
+f 21//23 35//23 36//23 23//23
+f 23//24 36//24 25//24 2//24
+f 25//25 37//25 38//25 26//25
+f 26//26 38//26 39//26 27//26
+f 27//27 39//27 40//27 28//27
+f 28//28 40//28 41//28 29//28
+f 29//29 41//29 42//29 30//29
+f 30//30 42//30 43//30 31//30
+f 31//31 43//31 44//31 32//31
+f 32//32 44//32 45//32 33//32
+f 33//33 45//33 46//33 34//33
+f 34//34 46//34 47//34 35//34
+f 35//35 47//35 48//35 36//35
+f 36//36 48//36 37//36 25//36
+f 37//37 49//37 50//37 38//37
+f 38//38 50//38 51//38 39//38
+f 39//39 51//39 52//39 40//39
+f 40//40 52//40 53//40 41//40
+f 41//41 53//41 54//41 42//41
+f 42//42 54//42 55//42 43//42
+f 43//43 55//43 56//43 44//43
+f 44//44 56//44 57//44 45//44
+f 45//45 57//45 58//45 46//45
+f 46//46 58//46 59//46 47//46
+f 47//47 59//47 60//47 48//47
+f 48//48 60//48 49//48 37//48
+f 49//49 61//49 62//49 50//49
+f 50//50 62//50 63//50 51//50
+f 51//51 63//51 64//51 52//51
+f 52//52 64//52 65//52 53//52
+f 53//53 65//53 66//53 54//53
+f 54//54 66//54 67//54 55//54
+f 55//55 67//55 68//55 56//55
+f 56//56 68//56 69//56 57//56
+f 57//57 69//57 70//57 58//57
+f 58//58 70//58 71//58 59//58
+f 59//59 71//59 72//59 60//59
+f 60//60 72//60 61//60 49//60
+f 61//61 73//61 74//61 62//61
+f 62//62 74//62 75//62 63//62
+f 63//63 75//63 76//63 64//63
+f 64//64 76//64 77//64 65//64
+f 65//65 77//65 78//65 66//65
+f 66//66 78//66 79//66 67//66
+f 67//67 79//67 80//67 68//67
+f 68//68 80//68 81//68 69//68
+f 69//69 81//69 82//69 70//69
+f 70//70 82//70 83//70 71//70
+f 71//71 83//71 84//71 72//71
+f 72//72 84//72 73//72 61//72
+f 73//73 85//73 86//73 74//73
+f 74//74 86//74 87//74 75//74
+f 75//75 87//75 88//75 76//75
+f 76//76 88//76 89//76 77//76
+f 77//77 89//77 90//77 78//77
+f 78//78 90//78 91//78 79//78
+f 79//79 91//79 92//79 80//79
+f 80//80 92//80 93//80 81//80
+f 81//81 93//81 94//81 82//81
+f 82//82 94//82 95//82 83//82
+f 83//83 95//83 96//83 84//83
+f 84//84 96//84 85//84 73//84
+f 85//85 97//85 98//85 86//85
+f 86//86 98//86 99//86 87//86
+f 87//87 99//87 100//87 88//87
+f 88//88 100//88 101//88 89//88
+f 89//89 101//89 102//89 90//89
+f 90//90 102//90 103//90 91//90
+f 91//91 103//91 104//91 92//91
+f 92//92 104//92 105//92 93//92
+f 93//93 105//93 106//93 94//93
+f 94//94 106//94 107//94 95//94
+f 95//95 107//95 108//95 96//95
+f 96//96 108//96 97//96 85//96
+f 97//97 109//97 110//97 98//97
+f 98//98 110//98 111//98 99//98
+f 99//99 111//99 112//99 100//99
+f 100//100 112//100 113//100 101//100
+f 101//101 113//101 114//101 102//101
+f 102//102 114//102 115//102 103//102
+f 103//103 115//103 116//103 104//103
+f 104//104 116//104 117//104 105//104
+f 105//105 117//105 118//105 106//105
+f 106//106 118//106 119//106 107//106
+f 107//107 119//107 120//107 108//107
+f 108//108 120//108 109//108 97//108
+f 109//109 121//109 122//109 110//109
+f 110//110 122//110 123//110 111//110
+f 111//111 123//111 124//111 112//111
+f 112//112 124//112 125//112 113//112
+f 113//113 125//113 126//113 114//113
+f 114//114 126//114 127//114 115//114
+f 115//115 127//115 128//115 116//115
+f 116//116 128//116 129//116 117//116
+f 117//117 129//117 130//117 118//117
+f 118//118 130//118 131//118 119//118
+f 119//119 131//119 132//119 120//119
+f 120//120 132//120 121//120 109//120
+f 121//121 133//121 134//121 122//121
+f 122//122 134//122 135//122 123//122
+f 123//123 135//123 136//123 124//123
+f 124//124 136//124 137//124 125//124
+f 125//125 137//125 138//125 126//125
+f 126//126 138//126 139//126 127//126
+f 127//127 139//127 140//127 128//127
+f 128//128 140//128 141//128 129//128
+f 129//129 141//129 142//129 130//129
+f 130//130 142//130 143//130 131//130
+f 131//131 143//131 144//131 132//131
+f 132//132 144//132 133//132 121//132
+f 133//133 145//133 146//133 134//133
+f 134//134 146//134 147//134 135//134
+f 135//135 147//135 148//135 136//135
+f 136//136 148//136 149//136 137//136
+f 137//137 149//137 150//137 138//137
+f 138//138 150//138 151//138 139//138
+f 139//139 151//139 152//139 140//139
+f 140//140 152//140 153//140 141//140
+f 141//141 153//141 154//141 142//141
+f 142//142 154//142 155//142 143//142
+f 143//143 155//143 156//143 144//143
+f 144//144 156//144 145//144 133//144
+f 145//145 157//145 158//145 146//145
+f 146//146 158//146 159//146 147//146
+f 147//147 159//147 160//147 148//147
+f 148//148 160//148 161//148 149//148
+f 149//149 161//149 162//149 150//149
+f 150//150 162//150 163//150 151//150
+f 151//151 163//151 164//151 152//151
+f 152//152 164//152 165//152 153//152
+f 153//153 165//153 166//153 154//153
+f 154//154 166//154 167//154 155//154
+f 155//155 167//155 168//155 156//155
+f 156//156 168//156 157//156 145//156
+f 157//157 169//157 170//157 158//157
+f 158//158 170//158 171//158 159//158
+f 159//159 171//159 172//159 160//159
+f 160//160 172//160 173//160 161//160
+f 161//161 173//161 174//161 162//161
+f 162//162 174//162 175//162 163//162
+f 163//163 175//163 176//163 164//163
+f 164//164 176//164 177//164 165//164
+f 165//165 177//165 178//165 166//165
+f 166//166 178//166 179//166 167//166
+f 167//167 179//167 180//167 168//167
+f 168//168 180//168 169//168 157//168
+f 169//169 181//169 182//169 170//169
+f 170//170 182//170 183//170 171//170
+f 171//171 183//171 184//171 172//171
+f 172//172 184//172 185//172 173//172
+f 173//173 185//173 186//173 174//173
+f 174//174 186//174 187//174 175//174
+f 175//175 187//175 188//175 176//175
+f 176//176 188//176 189//176 177//176
+f 177//177 189//177 190//177 178//177
+f 178//178 190//178 191//178 179//178
+f 179//179 191//179 192//179 180//179
+f 180//180 192//180 181//180 169//180
+f 181//181 193//181 194//181 182//181
+f 182//182 194//182 195//182 183//182
+f 183//183 195//183 196//183 184//183
+f 184//184 196//184 197//184 185//184
+f 185//185 197//185 198//185 186//185
+f 186//186 198//186 199//186 187//186
+f 187//187 199//187 200//187 188//187
+f 188//188 200//188 201//188 189//188
+f 189//189 201//189 202//189 190//189
+f 190//190 202//190 203//190 191//190
+f 191//191 203//191 204//191 192//191
+f 192//192 204//192 193//192 181//192
+f 193//193 205//193 206//193 194//193
+f 194//194 206//194 207//194 195//194
+f 195//195 207//195 208//195 196//195
+f 196//196 208//196 209//196 197//196
+f 197//197 209//197 210//197 198//197
+f 198//198 210//198 211//198 199//198
+f 199//199 211//199 212//199 200//199
+f 200//200 212//200 213//200 201//200
+f 201//201 213//201 214//201 202//201
+f 202//202 214//202 215//202 203//202
+f 203//203 215//203 216//203 204//203
+f 204//204 216//204 205//204 193//204
+f 205//205 217//205 218//205 206//205
+f 206//206 218//206 219//206 207//206
+f 207//207 219//207 220//207 208//207
+f 208//208 220//208 221//208 209//208
+f 209//209 221//209 222//209 210//209
+f 210//210 222//210 223//210 211//210
+f 211//211 223//211 224//211 212//211
+f 212//212 224//212 225//212 213//212
+f 213//213 225//213 226//213 214//213
+f 214//214 226//214 227//214 215//214
+f 215//215 227//215 228//215 216//215
+f 216//216 228//216 217//216 205//216
+f 217//217 229//217 230//217 218//217
+f 218//218 230//218 231//218 219//218
+f 219//219 231//219 232//219 220//219
+f 220//220 232//220 233//220 221//220
+f 221//221 233//221 234//221 222//221
+f 222//222 234//222 235//222 223//222
+f 223//223 235//223 236//223 224//223
+f 224//224 236//224 237//224 225//224
+f 225//225 237//225 238//225 226//225
+f 226//226 238//226 239//226 227//226
+f 227//227 239//227 240//227 228//227
+f 228//228 240//228 229//228 217//228
+f 229//229 241//229 242//229 230//229
+f 230//230 242//230 243//230 231//230
+f 231//231 243//231 244//231 232//231
+f 232//232 244//232 245//232 233//232
+f 233//233 245//233 246//233 234//233
+f 234//234 246//234 247//234 235//234
+f 235//235 247//235 248//235 236//235
+f 236//236 248//236 249//236 237//236
+f 237//237 249//237 250//237 238//237
+f 238//238 250//238 251//238 239//238
+f 239//239 251//239 252//239 240//239
+f 240//240 252//240 241//240 229//240
+f 241//241 253//241 254//241 242//241
+f 242//242 254//242 255//242 243//242
+f 243//243 255//243 256//243 244//243
+f 244//244 256//244 257//244 245//244
+f 245//245 257//245 258//245 246//245
+f 246//246 258//246 259//246 247//246
+f 247//247 259//247 260//247 248//247
+f 248//248 260//248 261//248 249//248
+f 249//249 261//249 262//249 250//249
+f 250//250 262//250 263//250 251//250
+f 251//251 263//251 264//251 252//251
+f 252//252 264//252 253//252 241//252
+f 253//253 265//253 266//253 254//253
+f 254//254 266//254 267//254 255//254
+f 255//255 267//255 268//255 256//255
+f 256//256 268//256 269//256 257//256
+f 257//257 269//257 270//257 258//257
+f 258//258 270//258 271//258 259//258
+f 259//259 271//259 272//259 260//259
+f 260//260 272//260 273//260 261//260
+f 261//261 273//261 274//261 262//261
+f 262//262 274//262 275//262 263//262
+f 263//263 275//263 276//263 264//263
+f 264//264 276//264 265//264 253//264
+f 265//265 277//265 278//265 266//265
+f 266//266 278//266 279//266 267//266
+f 267//267 279//267 280//267 268//267
+f 268//268 280//268 281//268 269//268
+f 269//269 281//269 282//269 270//269
+f 270//270 282//270 283//270 271//270
+f 271//271 283//271 284//271 272//271
+f 272//272 284//272 285//272 273//272
+f 273//273 285//273 286//273 274//273
+f 274//274 286//274 287//274 275//274
+f 275//275 287//275 288//275 276//275
+f 276//276 288//276 277//276 265//276
+f 277//277 289//277 290//277 278//277
+f 278//278 290//278 291//278 279//278
+f 279//279 291//279 292//279 280//279
+f 280//280 292//280 293//280 281//280
+f 281//281 293//281 294//281 282//281
+f 282//282 294//282 295//282 283//282
+f 283//283 295//283 296//283 284//283
+f 284//284 296//284 297//284 285//284
+f 285//285 297//285 298//285 286//285
+f 286//286 298//286 299//286 287//286
+f 287//287 299//287 300//287 288//287
+f 288//288 300//288 289//288 277//288
+f 289//6 301//6 302//6 290//6
+f 290//5 302//5 303//5 291//5
+f 291//4 303//4 304//4 292//4
+f 292//3 304//3 305//3 293//3
+f 293//2 305//2 306//2 294//2
+f 294//1 306//1 307//1 295//1
+f 295//12 307//12 308//12 296//12
+f 296//289 308//289 309//289 297//289
+f 297//10 309//10 310//10 298//10
+f 298//9 310//9 311//9 299//9
+f 299//290 311//290 312//290 300//290
+f 300//7 312//7 301//7 289//7
+f 301//18 313//18 314//18 302//18
+f 302//17 314//17 315//17 303//17
+f 303//16 315//16 316//16 304//16
+f 304//15 316//15 317//15 305//15
+f 305//14 317//14 318//14 306//14
+f 306//13 318//13 319//13 307//13
+f 307//24 319//24 320//24 308//24
+f 308//23 320//23 321//23 309//23
+f 309//22 321//22 322//22 310//22
+f 310//21 322//21 323//21 311//21
+f 311//20 323//20 324//20 312//20
+f 312//19 324//19 313//19 301//19
+f 313//30 325//30 326//30 314//30
+f 314//29 326//29 327//29 315//29
+f 315//28 327//28 328//28 316//28
+f 316//27 328//27 329//27 317//27
+f 317//26 329//26 330//26 318//26
+f 318//25 330//25 331//25 319//25
+f 319//36 331//36 332//36 320//36
+f 320//35 332//35 333//35 321//35
+f 321//34 333//34 334//34 322//34
+f 322//33 334//33 335//33 323//33
+f 323//32 335//32 336//32 324//32
+f 324//31 336//31 325//31 313//31
+f 325//42 337//42 338//42 326//42
+f 326//41 338//41 339//41 327//41
+f 327//40 339//40 340//40 328//40
+f 328//39 340//39 341//39 329//39
+f 329//38 341//38 342//38 330//38
+f 330//37 342//37 343//37 331//37
+f 331//48 343//48 344//48 332//48
+f 332//291 344//291 345//291 333//291
+f 333//46 345//46 346//46 334//46
+f 334//45 346//45 347//45 335//45
+f 335//44 347//44 348//44 336//44
+f 336//43 348//43 337//43 325//43
+f 337//54 349//54 350//54 338//54
+f 338//53 350//53 351//53 339//53
+f 339//52 351//52 352//52 340//52
+f 340//51 352//51 353//51 341//51
+f 341//50 353//50 354//50 342//50
+f 342//49 354//49 355//49 343//49
+f 343//60 355//60 356//60 344//60
+f 344//292 356//292 357//292 345//292
+f 345//58 357//58 358//58 346//58
+f 346//57 358//57 359//57 347//57
+f 347//56 359//56 360//56 348//56
+f 348//55 360//55 349//55 337//55
+f 349//66 361//66 362//66 350//66
+f 350//65 362//65 363//65 351//65
+f 351//64 363//64 364//64 352//64
+f 352//63 364//63 365//63 353//63
+f 353//62 365//62 366//62 354//62
+f 354//61 366//61 367//61 355//61
+f 355//72 367//72 368//72 356//72
+f 356//293 368//293 369//293 357//293
+f 357//70 369//70 370//70 358//70
+f 358//69 370//69 371//69 359//69
+f 359//68 371//68 372//68 360//68
+f 360//67 372//67 361//67 349//67
+f 361//78 373//78 374//78 362//78
+f 362//77 374//77 375//77 363//77
+f 363//76 375//76 376//76 364//76
+f 364//75 376//75 377//75 365//75
+f 365//74 377//74 378//74 366//74
+f 366//73 378//73 379//73 367//73
+f 367//84 379//84 380//84 368//84
+f 368//83 380//83 381//83 369//83
+f 369//82 381//82 382//82 370//82
+f 370//81 382//81 383//81 371//81
+f 371//294 383//294 384//294 372//294
+f 372//79 384//79 373//79 361//79
+f 373//90 385//90 386//90 374//90
+f 374//89 386//89 387//89 375//89
+f 375//88 387//88 388//88 376//88
+f 376//87 388//87 389//87 377//87
+f 377//86 389//86 390//86 378//86
+f 378//85 390//85 391//85 379//85
+f 379//96 391//96 392//96 380//96
+f 380//295 392//295 393//295 381//295
+f 381//94 393//94 394//94 382//94
+f 382//93 394//93 395//93 383//93
+f 383//296 395//296 396//296 384//296
+f 384//91 396//91 385//91 373//91
+f 385//102 397//102 398//102 386//102
+f 386//101 398//101 399//101 387//101
+f 387//100 399//100 400//100 388//100
+f 388//99 400//99 401//99 389//99
+f 389//98 401//98 402//98 390//98
+f 390//97 402//97 403//97 391//97
+f 391//108 403//108 404//108 392//108
+f 392//297 404//297 405//297 393//297
+f 393//106 405//106 406//106 394//106
+f 394//105 406//105 407//105 395//105
+f 395//104 407//104 408//104 396//104
+f 396//103 408//103 397//103 385//103
+f 397//114 409//114 410//114 398//114
+f 398//113 410//113 411//113 399//113
+f 399//112 411//112 412//112 400//112
+f 400//111 412//111 413//111 401//111
+f 401//110 413//110 414//110 402//110
+f 402//109 414//109 415//109 403//109
+f 403//120 415//120 416//120 404//120
+f 404//298 416//298 417//298 405//298
+f 405//118 417//118 418//118 406//118
+f 406//117 418//117 419//117 407//117
+f 407//299 419//299 420//299 408//299
+f 408//115 420//115 409//115 397//115
+f 409//126 421//126 422//126 410//126
+f 410//125 422//125 423//125 411//125
+f 411//124 423//124 424//124 412//124
+f 412//300 424//300 425//300 413//300
+f 413//122 425//122 426//122 414//122
+f 414//121 426//121 427//121 415//121
+f 415//132 427//132 428//132 416//132
+f 416//301 428//301 429//301 417//301
+f 417//130 429//130 430//130 418//130
+f 418//129 430//129 431//129 419//129
+f 419//302 431//302 432//302 420//302
+f 420//127 432//127 421//127 409//127
+f 421//138 433//138 434//138 422//138
+f 422//137 434//137 435//137 423//137
+f 423//136 435//136 436//136 424//136
+f 424//135 436//135 437//135 425//135
+f 425//303 437//303 438//303 426//303
+f 426//133 438//133 439//133 427//133
+f 427//144 439//144 440//144 428//144
+f 428//143 440//143 441//143 429//143
+f 429//142 441//142 442//142 430//142
+f 430//141 442//141 443//141 431//141
+f 431//304 443//304 444//304 432//304
+f 432//139 444//139 433//139 421//139
+f 433//150 445//150 446//150 434//150
+f 434//149 446//149 447//149 435//149
+f 435//148 447//148 448//148 436//148
+f 436//147 448//147 449//147 437//147
+f 437//305 449//305 450//305 438//305
+f 438//145 450//145 451//145 439//145
+f 439//156 451//156 452//156 440//156
+f 440//155 452//155 453//155 441//155
+f 441//154 453//154 454//154 442//154
+f 442//153 454//153 455//153 443//153
+f 443//152 455//152 456//152 444//152
+f 444//151 456//151 445//151 433//151
+f 445//162 457//162 458//162 446//162
+f 446//161 458//161 459//161 447//161
+f 447//160 459//160 460//160 448//160
+f 448//159 460//159 461//159 449//159
+f 449//158 461//158 462//158 450//158
+f 450//157 462//157 463//157 451//157
+f 451//168 463//168 464//168 452//168
+f 452//167 464//167 465//167 453//167
+f 453//166 465//166 466//166 454//166
+f 454//165 466//165 467//165 455//165
+f 455//164 467//164 468//164 456//164
+f 456//163 468//163 457//163 445//163
+f 457//174 469//174 470//174 458//174
+f 458//173 470//173 471//173 459//173
+f 459//172 471//172 472//172 460//172
+f 460//171 472//171 473//171 461//171
+f 461//170 473//170 474//170 462//170
+f 462//169 474//169 475//169 463//169
+f 463//180 475//180 476//180 464//180
+f 464//179 476//179 477//179 465//179
+f 465//178 477//178 478//178 466//178
+f 466//177 478//177 479//177 467//177
+f 467//176 479//176 480//176 468//176
+f 468//175 480//175 469//175 457//175
+f 469//186 481//186 482//186 470//186
+f 470//185 482//185 483//185 471//185
+f 471//184 483//184 484//184 472//184
+f 472//183 484//183 485//183 473//183
+f 473//182 485//182 486//182 474//182
+f 474//181 486//181 487//181 475//181
+f 475//192 487//192 488//192 476//192
+f 476//191 488//191 489//191 477//191
+f 477//190 489//190 490//190 478//190
+f 478//189 490//189 491//189 479//189
+f 479//188 491//188 492//188 480//188
+f 480//187 492//187 481//187 469//187
+f 481//198 493//198 494//198 482//198
+f 482//197 494//197 495//197 483//197
+f 483//196 495//196 496//196 484//196
+f 484//195 496//195 497//195 485//195
+f 485//194 497//194 498//194 486//194
+f 486//193 498//193 499//193 487//193
+f 487//204 499//204 500//204 488//204
+f 488//306 500//306 501//306 489//306
+f 489//202 501//202 502//202 490//202
+f 490//201 502//201 503//201 491//201
+f 491//307 503//307 504//307 492//307
+f 492//199 504//199 493//199 481//199
+f 493//210 505//210 506//210 494//210
+f 494//209 506//209 507//209 495//209
+f 495//208 507//208 508//208 496//208
+f 496//207 508//207 509//207 497//207
+f 497//206 509//206 510//206 498//206
+f 498//205 510//205 511//205 499//205
+f 499//216 511//216 512//216 500//216
+f 500//308 512//308 513//308 501//308
+f 501//214 513//214 514//214 502//214
+f 502//213 514//213 515//213 503//213
+f 503//309 515//309 516//309 504//309
+f 504//211 516//211 505//211 493//211
+f 505//222 517//222 518//222 506//222
+f 506//221 518//221 519//221 507//221
+f 507//220 519//220 520//220 508//220
+f 508//219 520//219 521//219 509//219
+f 509//218 521//218 522//218 510//218
+f 510//217 522//217 523//217 511//217
+f 511//228 523//228 524//228 512//228
+f 512//310 524//310 525//310 513//310
+f 513//226 525//226 526//226 514//226
+f 514//225 526//225 527//225 515//225
+f 515//224 527//224 528//224 516//224
+f 516//223 528//223 517//223 505//223
+f 517//234 529//234 530//234 518//234
+f 518//233 530//233 531//233 519//233
+f 519//232 531//232 532//232 520//232
+f 520//231 532//231 533//231 521//231
+f 521//230 533//230 534//230 522//230
+f 522//229 534//229 535//229 523//229
+f 523//240 535//240 536//240 524//240
+f 524//311 536//311 537//311 525//311
+f 525//238 537//238 538//238 526//238
+f 526//237 538//237 539//237 527//237
+f 527//236 539//236 540//236 528//236
+f 528//235 540//235 529//235 517//235
+f 529//246 541//246 542//246 530//246
+f 530//245 542//245 543//245 531//245
+f 531//244 543//244 544//244 532//244
+f 532//243 544//243 545//243 533//243
+f 533//242 545//242 546//242 534//242
+f 534//241 546//241 547//241 535//241
+f 535//252 547//252 548//252 536//252
+f 536//251 548//251 549//251 537//251
+f 537//250 549//250 550//250 538//250
+f 538//249 550//249 551//249 539//249
+f 539//248 551//248 552//248 540//248
+f 540//247 552//247 541//247 529//247
+f 541//258 553//258 554//258 542//258
+f 542//257 554//257 555//257 543//257
+f 543//256 555//256 556//256 544//256
+f 544//255 556//255 557//255 545//255
+f 545//254 557//254 558//254 546//254
+f 546//253 558//253 559//253 547//253
+f 547//264 559//264 560//264 548//264
+f 548//263 560//263 561//263 549//263
+f 549//262 561//262 562//262 550//262
+f 550//261 562//261 563//261 551//261
+f 551//312 563//312 564//312 552//312
+f 552//259 564//259 553//259 541//259
+f 553//270 565//270 566//270 554//270
+f 554//269 566//269 567//269 555//269
+f 555//313 567//313 568//313 556//313
+f 556//267 568//267 569//267 557//267
+f 557//266 569//266 570//266 558//266
+f 558//265 570//265 571//265 559//265
+f 559//276 571//276 572//276 560//276
+f 560//275 572//275 573//275 561//275
+f 561//274 573//274 574//274 562//274
+f 562//273 574//273 575//273 563//273
+f 563//314 575//314 576//314 564//314
+f 564//271 576//271 565//271 553//271
+f 565//282 1//282 4//282 566//282
+f 566//281 4//281 6//281 567//281
+f 567//280 6//280 8//280 568//280
+f 568//279 8//279 10//279 569//279
+f 569//278 10//278 12//278 570//278
+f 570//277 12//277 14//277 571//277
+f 571//288 14//288 16//288 572//288
+f 572//315 16//315 18//315 573//315
+f 573//286 18//286 20//286 574//286
+f 574//285 20//285 22//285 575//285
+f 575//316 22//316 24//316 576//316
+f 576//283 24//283 1//283 565//283
diff --git a/data/torus/torus_with_plane.mtl b/data/torus/torus_with_plane.mtl
new file mode 100644
index 000000000..70d3ba1da
--- /dev/null
+++ b/data/torus/torus_with_plane.mtl
@@ -0,0 +1,10 @@
+# Blender MTL File: 'None'
+# Material Count: 1
+
+newmtl None
+Ns 0
+Ka 0.000000 0.000000 0.000000
+Kd 0.8 0.8 0.8
+Ks 0.8 0.8 0.8
+d 1
+illum 2
diff --git a/data/torus/torus_with_plane.obj b/data/torus/torus_with_plane.obj
new file mode 100644
index 000000000..b036d9fdd
--- /dev/null
+++ b/data/torus/torus_with_plane.obj
@@ -0,0 +1,9384 @@
+# Blender v2.77 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib torus_with_plane.mtl
+o Plane
+v -2.312398 -6.126618 0.566384
+v 6.032325 -2.575601 0.280679
+v -5.874205 2.203907 0.074895
+v 2.470518 5.754926 -0.210810
+v -5.804365 2.040563 0.084532
+v -5.734526 1.877220 0.094169
+v -5.664686 1.713876 0.103806
+v -5.594847 1.550532 0.113443
+v -5.525007 1.387189 0.123080
+v -5.455168 1.223845 0.132717
+v -5.385328 1.060502 0.142354
+v -5.315490 0.897157 0.151991
+v -5.245650 0.733814 0.161628
+v -5.175811 0.570470 0.171265
+v -5.105971 0.407127 0.180902
+v -5.036132 0.243783 0.190539
+v -4.966292 0.080439 0.200176
+v -4.896453 -0.082904 0.209813
+v -4.826613 -0.246248 0.219450
+v -4.756775 -0.409592 0.229087
+v -4.686935 -0.572935 0.238724
+v -4.617096 -0.736279 0.248362
+v -4.547256 -0.899623 0.257998
+v -4.477417 -1.062966 0.267636
+v -4.407578 -1.226310 0.277273
+v -4.337738 -1.389654 0.286910
+v -4.267900 -1.552997 0.296547
+v -4.198060 -1.716341 0.306184
+v -4.128221 -1.879685 0.315821
+v -4.058381 -2.043028 0.325458
+v -3.988542 -2.206372 0.335095
+v -3.918703 -2.369716 0.344732
+v -3.848863 -2.533059 0.354369
+v -3.779024 -2.696403 0.364006
+v -3.709185 -2.859747 0.373643
+v -3.639345 -3.023091 0.383280
+v -3.569506 -3.186434 0.392917
+v -3.499667 -3.349777 0.402554
+v -3.429827 -3.513121 0.412191
+v -3.359988 -3.676465 0.421829
+v -3.290149 -3.839808 0.431465
+v -3.220309 -4.003152 0.441103
+v -3.150470 -4.166496 0.450740
+v -3.080631 -4.329839 0.460377
+v -3.010791 -4.493183 0.470014
+v -2.940952 -4.656527 0.479651
+v -2.871112 -4.819870 0.489288
+v -2.801273 -4.983214 0.498925
+v -2.731434 -5.146557 0.508562
+v -2.661594 -5.309901 0.518199
+v -2.591755 -5.473244 0.527836
+v -2.521916 -5.636589 0.537473
+v -2.452076 -5.799932 0.547110
+v -2.382237 -5.963276 0.556747
+v -2.148776 -6.056991 0.560782
+v -1.985154 -5.987363 0.555180
+v -1.821532 -5.917735 0.549578
+v -1.657910 -5.848107 0.543976
+v -1.494288 -5.778480 0.538374
+v -1.330665 -5.708852 0.532772
+v -1.167043 -5.639224 0.527170
+v -1.003422 -5.569596 0.521568
+v -0.839799 -5.499969 0.515965
+v -0.676177 -5.430341 0.510363
+v -0.512555 -5.360713 0.504761
+v -0.348933 -5.291085 0.499159
+v -0.185311 -5.221457 0.493557
+v -0.021689 -5.151829 0.487955
+v 0.141933 -5.082201 0.482353
+v 0.305555 -5.012573 0.476751
+v 0.469177 -4.942945 0.471149
+v 0.632799 -4.873318 0.465547
+v 0.796421 -4.803690 0.459945
+v 0.960043 -4.734062 0.454343
+v 1.123665 -4.664434 0.448741
+v 1.287287 -4.594807 0.443139
+v 1.450909 -4.525179 0.437537
+v 1.614531 -4.455551 0.431935
+v 1.778153 -4.385922 0.426333
+v 1.941775 -4.316295 0.420731
+v 2.105397 -4.246667 0.415129
+v 2.269019 -4.177039 0.409527
+v 2.432641 -4.107412 0.403924
+v 2.596263 -4.037785 0.398322
+v 2.759885 -3.968157 0.392720
+v 2.923507 -3.898529 0.387118
+v 3.087129 -3.828902 0.381516
+v 3.250751 -3.759273 0.375914
+v 3.414372 -3.689645 0.370312
+v 3.577994 -3.620018 0.364710
+v 3.741616 -3.550390 0.359108
+v 3.905239 -3.480762 0.353506
+v 4.068861 -3.411134 0.347904
+v 4.232483 -3.341506 0.342302
+v 4.396105 -3.271878 0.336700
+v 4.559727 -3.202251 0.331098
+v 4.723349 -3.132623 0.325496
+v 4.886971 -3.062995 0.319894
+v 5.050592 -2.993367 0.314292
+v 5.214214 -2.923740 0.308690
+v 5.377837 -2.854112 0.303087
+v 5.541458 -2.784484 0.297485
+v 5.705081 -2.714856 0.291883
+v 5.868702 -2.645229 0.286281
+v 5.962485 -2.412257 0.271042
+v 5.892646 -2.248913 0.261405
+v 5.822806 -2.085569 0.251768
+v 5.752967 -1.922226 0.242131
+v 5.683127 -1.758882 0.232494
+v 5.613288 -1.595538 0.222857
+v 5.543449 -1.432195 0.213220
+v 5.473610 -1.268851 0.203583
+v 5.403770 -1.105507 0.193946
+v 5.333931 -0.942164 0.184309
+v 5.264091 -0.778820 0.174672
+v 5.194252 -0.615476 0.165035
+v 5.124413 -0.452132 0.155398
+v 5.054573 -0.288789 0.145761
+v 4.984735 -0.125445 0.136124
+v 4.914895 0.037898 0.126487
+v 4.845056 0.201242 0.116849
+v 4.775216 0.364586 0.107213
+v 4.705377 0.527929 0.097575
+v 4.635537 0.691273 0.087938
+v 4.565698 0.854617 0.078301
+v 4.495859 1.017960 0.068664
+v 4.426020 1.181304 0.059027
+v 4.356180 1.344648 0.049390
+v 4.286341 1.507991 0.039753
+v 4.216501 1.671335 0.030116
+v 4.146662 1.834678 0.020479
+v 4.076822 1.998022 0.010842
+v 4.006983 2.161365 0.001205
+v 3.937144 2.324709 -0.008432
+v 3.867305 2.488053 -0.018069
+v 3.797465 2.651397 -0.027706
+v 3.727626 2.814740 -0.037343
+v 3.657787 2.978083 -0.046980
+v 3.587947 3.141428 -0.056617
+v 3.518108 3.304771 -0.066254
+v 3.448268 3.468114 -0.075891
+v 3.378429 3.631458 -0.085528
+v 3.308590 3.794802 -0.095165
+v 3.238750 3.958145 -0.104803
+v 3.168911 4.121490 -0.114440
+v 3.099072 4.284833 -0.124077
+v 3.029233 4.448177 -0.133714
+v 2.959393 4.611520 -0.143351
+v 2.889554 4.774864 -0.152988
+v 2.819715 4.938208 -0.162625
+v 2.749875 5.101552 -0.172262
+v 2.680036 5.264896 -0.181899
+v 2.610196 5.428238 -0.191536
+v 2.540357 5.591582 -0.201173
+v 2.306895 5.685298 -0.205208
+v 2.143273 5.615670 -0.199606
+v 1.979651 5.546042 -0.194004
+v 1.816030 5.476415 -0.188402
+v 1.652407 5.406787 -0.182800
+v 1.488786 5.337159 -0.177198
+v 1.325163 5.267531 -0.171596
+v 1.161541 5.197904 -0.165994
+v 0.997919 5.128276 -0.160392
+v 0.834297 5.058648 -0.154789
+v 0.670675 4.989020 -0.149187
+v 0.507053 4.919393 -0.143585
+v 0.343431 4.849765 -0.137983
+v 0.179809 4.780137 -0.132381
+v 0.016187 4.710509 -0.126779
+v -0.147435 4.640882 -0.121177
+v -0.311057 4.571253 -0.115575
+v -0.474679 4.501625 -0.109973
+v -0.638301 4.431997 -0.104371
+v -0.801923 4.362370 -0.098769
+v -0.965545 4.292742 -0.093167
+v -1.129167 4.223114 -0.087565
+v -1.292789 4.153486 -0.081963
+v -1.456411 4.083858 -0.076361
+v -1.620033 4.014231 -0.070759
+v -1.783655 3.944603 -0.065157
+v -1.947277 3.874975 -0.059554
+v -2.110899 3.805346 -0.053952
+v -2.274521 3.735718 -0.048350
+v -2.438143 3.666091 -0.042748
+v -2.601765 3.596463 -0.037146
+v -2.765387 3.526835 -0.031544
+v -2.929009 3.457207 -0.025942
+v -3.092631 3.387580 -0.020340
+v -3.256253 3.317952 -0.014738
+v -3.419875 3.248324 -0.009136
+v -3.583497 3.178696 -0.003534
+v -3.747118 3.109069 0.002068
+v -3.910740 3.039441 0.007670
+v -4.074363 2.969813 0.013272
+v -4.237985 2.900185 0.018874
+v -4.401607 2.830558 0.024476
+v -4.565228 2.760930 0.030078
+v -4.728850 2.691302 0.035680
+v -4.892472 2.621674 0.041282
+v -5.056094 2.552047 0.046885
+v -5.219716 2.482419 0.052487
+v -5.383339 2.412791 0.058089
+v -5.546961 2.343162 0.063691
+v -5.710583 2.273535 0.069293
+v -5.640743 2.110191 0.078930
+v -5.407282 2.016475 0.082965
+v -5.173820 1.922760 0.087000
+v -4.940358 1.829044 0.091035
+v -4.706897 1.735328 0.095070
+v -4.473435 1.641612 0.099105
+v -4.239974 1.547897 0.103140
+v -4.006513 1.454180 0.107175
+v -3.773051 1.360465 0.111210
+v -3.539590 1.266749 0.115245
+v -3.306129 1.173033 0.119280
+v -3.072667 1.079317 0.123315
+v -2.839206 0.985601 0.127350
+v -2.605745 0.891885 0.131385
+v -2.372283 0.798169 0.135420
+v -2.138822 0.704454 0.139455
+v -1.905361 0.610738 0.143490
+v -1.671899 0.517022 0.147525
+v -1.438438 0.423306 0.151560
+v -1.204977 0.329590 0.155595
+v -0.971515 0.235874 0.159630
+v -0.738054 0.142159 0.163665
+v -0.504593 0.048443 0.167700
+v -0.271131 -0.045273 0.171735
+v -0.037670 -0.138989 0.175770
+v 0.195791 -0.232705 0.179805
+v 0.429253 -0.326421 0.183840
+v 0.662714 -0.420136 0.187875
+v 0.896175 -0.513852 0.191910
+v 1.129637 -0.607568 0.195945
+v 1.363098 -0.701284 0.199980
+v 1.596559 -0.795000 0.204015
+v 1.830021 -0.888716 0.208049
+v 2.063482 -0.982431 0.212084
+v 2.296943 -1.076147 0.216119
+v 2.530405 -1.169863 0.220154
+v 2.763866 -1.263579 0.224189
+v 2.997327 -1.357295 0.228224
+v 3.230788 -1.451011 0.232259
+v 3.464250 -1.544726 0.236294
+v 3.697711 -1.638442 0.240329
+v 3.931173 -1.732158 0.244364
+v 4.164635 -1.825874 0.248399
+v 4.398096 -1.919590 0.252434
+v 4.631557 -2.013306 0.256469
+v 4.865018 -2.107021 0.260504
+v 5.098479 -2.200737 0.264539
+v 5.331941 -2.294453 0.268574
+v 5.565402 -2.388169 0.272609
+v 5.798862 -2.481885 0.276644
+v -5.477121 2.179819 0.073328
+v -5.243659 2.086103 0.077363
+v -5.313498 2.249447 0.067726
+v -5.010198 1.992388 0.081398
+v -5.080037 2.155731 0.071761
+v -5.149877 2.319074 0.062124
+v -4.776736 1.898672 0.085433
+v -4.846576 2.062015 0.075796
+v -4.916415 2.225359 0.066159
+v -4.986255 2.388702 0.056522
+v -4.543275 1.804956 0.089468
+v -4.613114 1.968299 0.079831
+v -4.682954 2.131643 0.070194
+v -4.752793 2.294986 0.060557
+v -4.822633 2.458330 0.050920
+v -4.309813 1.711240 0.093503
+v -4.379653 1.874583 0.083866
+v -4.449492 2.037927 0.074229
+v -4.519332 2.201271 0.064592
+v -4.589171 2.364614 0.054955
+v -4.659011 2.527958 0.045318
+v -4.076352 1.617524 0.097538
+v -4.146192 1.780868 0.087901
+v -4.216031 1.944211 0.078264
+v -4.285871 2.107555 0.068627
+v -4.355710 2.270899 0.058990
+v -4.425550 2.434242 0.049352
+v -4.495389 2.597585 0.039715
+v -3.842891 1.523808 0.101573
+v -3.912730 1.687152 0.091936
+v -3.982570 1.850495 0.082299
+v -4.052409 2.013839 0.072662
+v -4.122249 2.177183 0.063025
+v -4.192088 2.340526 0.053387
+v -4.261928 2.503870 0.043751
+v -4.331767 2.667213 0.034113
+v -3.609429 1.430092 0.105608
+v -3.679269 1.593436 0.095971
+v -3.749108 1.756780 0.086334
+v -3.818948 1.920124 0.076697
+v -3.888787 2.083467 0.067060
+v -3.958627 2.246810 0.057422
+v -4.028465 2.410154 0.047786
+v -4.098306 2.573498 0.038148
+v -4.168145 2.736841 0.028511
+v -3.375968 1.336377 0.109643
+v -3.445807 1.499720 0.100006
+v -3.515647 1.663064 0.090369
+v -3.585486 1.826408 0.080732
+v -3.655326 1.989751 0.071095
+v -3.725165 2.153095 0.061457
+v -3.795005 2.316438 0.051821
+v -3.864844 2.479782 0.042183
+v -3.934684 2.643125 0.032546
+v -4.004523 2.806469 0.022909
+v -3.142507 1.242661 0.113678
+v -3.212346 1.406005 0.104041
+v -3.282185 1.569348 0.094404
+v -3.352025 1.732692 0.084767
+v -3.421864 1.896036 0.075130
+v -3.491704 2.059379 0.065492
+v -3.561543 2.222723 0.055856
+v -3.631382 2.386066 0.046218
+v -3.701222 2.549410 0.036581
+v -3.771061 2.712753 0.026944
+v -3.840901 2.876097 0.017307
+v -2.909045 1.148945 0.117713
+v -2.978885 1.312288 0.108076
+v -3.048724 1.475632 0.098439
+v -3.118563 1.638976 0.088801
+v -3.188403 1.802320 0.079165
+v -3.258242 1.965663 0.069527
+v -3.328082 2.129007 0.059891
+v -3.397921 2.292350 0.050253
+v -3.467761 2.455694 0.040616
+v -3.537600 2.619037 0.030979
+v -3.607439 2.782381 0.021342
+v -3.677279 2.945725 0.011705
+v -2.675584 1.055229 0.121748
+v -2.745423 1.218573 0.112111
+v -2.815263 1.381916 0.102473
+v -2.885102 1.545260 0.092836
+v -2.954941 1.708604 0.083200
+v -3.024781 1.871947 0.073562
+v -3.094620 2.035291 0.063925
+v -3.164460 2.198635 0.054288
+v -3.234299 2.361978 0.044651
+v -3.304139 2.525321 0.035014
+v -3.373978 2.688665 0.025377
+v -3.443818 2.852009 0.015740
+v -3.513657 3.015353 0.006103
+v -2.442123 0.961513 0.125782
+v -2.511962 1.124857 0.116146
+v -2.581802 1.288201 0.106508
+v -2.651641 1.451544 0.096871
+v -2.721480 1.614888 0.087234
+v -2.791320 1.778232 0.077597
+v -2.861159 1.941575 0.067960
+v -2.930999 2.104919 0.058323
+v -3.000838 2.268262 0.048686
+v -3.070677 2.431606 0.039049
+v -3.140517 2.594950 0.029412
+v -3.210356 2.758293 0.019775
+v -3.280196 2.921637 0.010138
+v -3.350035 3.084981 0.000501
+v -2.208661 0.867797 0.129817
+v -2.278501 1.031141 0.120181
+v -2.348340 1.194485 0.110543
+v -2.418180 1.357828 0.100906
+v -2.488019 1.521172 0.091269
+v -2.557858 1.684516 0.081632
+v -2.627698 1.847859 0.071995
+v -2.697537 2.011203 0.062358
+v -2.767377 2.174546 0.052721
+v -2.837216 2.337890 0.043084
+v -2.907056 2.501234 0.033447
+v -2.976895 2.664578 0.023810
+v -3.046734 2.827921 0.014173
+v -3.116574 2.991265 0.004536
+v -3.186413 3.154608 -0.005101
+v -1.975200 0.774081 0.133852
+v -2.045039 0.937425 0.124216
+v -2.114879 1.100769 0.114578
+v -2.184718 1.264112 0.104941
+v -2.254558 1.427456 0.095304
+v -2.324397 1.590800 0.085667
+v -2.394237 1.754144 0.076030
+v -2.464076 1.917487 0.066393
+v -2.533916 2.080831 0.056756
+v -2.603755 2.244174 0.047119
+v -2.673594 2.407518 0.037482
+v -2.743433 2.570862 0.027845
+v -2.813273 2.734205 0.018208
+v -2.883112 2.897548 0.008571
+v -2.952952 3.060892 -0.001066
+v -3.022791 3.224236 -0.010703
+v -1.741739 0.680366 0.137887
+v -1.811578 0.843709 0.128251
+v -1.881418 1.007053 0.118613
+v -1.951257 1.170397 0.108976
+v -2.021096 1.333740 0.099339
+v -2.090936 1.497084 0.089702
+v -2.160775 1.660428 0.080065
+v -2.230615 1.823772 0.070428
+v -2.300454 1.987115 0.060791
+v -2.370294 2.150458 0.051154
+v -2.440133 2.313802 0.041517
+v -2.509972 2.477146 0.031880
+v -2.579812 2.640490 0.022243
+v -2.649651 2.803833 0.012606
+v -2.719491 2.967177 0.002969
+v -2.789330 3.130521 -0.006668
+v -2.859169 3.293864 -0.016305
+v -1.508277 0.586650 0.141922
+v -1.578117 0.749993 0.132286
+v -1.647956 0.913337 0.122648
+v -1.717796 1.076681 0.113011
+v -1.787635 1.240025 0.103374
+v -1.857474 1.403368 0.093737
+v -1.927314 1.566712 0.084100
+v -1.997153 1.730055 0.074463
+v -2.066993 1.893399 0.064826
+v -2.136832 2.056743 0.055189
+v -2.206672 2.220086 0.045552
+v -2.276511 2.383430 0.035915
+v -2.346350 2.546774 0.026278
+v -2.416190 2.710117 0.016641
+v -2.486029 2.873461 0.007004
+v -2.555869 3.036804 -0.002633
+v -2.625708 3.200148 -0.012270
+v -2.695547 3.363492 -0.021907
+v -1.274816 0.492934 0.145957
+v -1.344656 0.656278 0.136321
+v -1.414495 0.819621 0.126683
+v -1.484334 0.982965 0.117046
+v -1.554174 1.146308 0.107409
+v -1.624013 1.309652 0.097772
+v -1.693853 1.472996 0.088135
+v -1.763692 1.636340 0.078498
+v -1.833531 1.799683 0.068861
+v -1.903371 1.963027 0.059224
+v -1.973210 2.126370 0.049587
+v -2.043050 2.289714 0.039950
+v -2.112889 2.453058 0.030313
+v -2.182729 2.616402 0.020676
+v -2.252568 2.779745 0.011039
+v -2.322407 2.943089 0.001402
+v -2.392247 3.106432 -0.008235
+v -2.462086 3.269776 -0.017872
+v -2.531925 3.433120 -0.027509
+v -1.041355 0.399218 0.149992
+v -1.111194 0.562562 0.140356
+v -1.181034 0.725905 0.130718
+v -1.250873 0.889249 0.121081
+v -1.320712 1.052593 0.111444
+v -1.390552 1.215936 0.101807
+v -1.460391 1.379280 0.092170
+v -1.530231 1.542624 0.082533
+v -1.600070 1.705968 0.072896
+v -1.669910 1.869311 0.063259
+v -1.739749 2.032655 0.053622
+v -1.809589 2.195998 0.043985
+v -1.879428 2.359342 0.034348
+v -1.949267 2.522686 0.024711
+v -2.019107 2.686029 0.015074
+v -2.088946 2.849373 0.005437
+v -2.158785 3.012717 -0.004200
+v -2.228625 3.176060 -0.013837
+v -2.298464 3.339404 -0.023474
+v -2.368304 3.502747 -0.033111
+v -0.807893 0.305502 0.154027
+v -0.877733 0.468846 0.144391
+v -0.947572 0.632190 0.134753
+v -1.017412 0.795533 0.125116
+v -1.087251 0.958877 0.115479
+v -1.157091 1.122221 0.105842
+v -1.226930 1.285564 0.096205
+v -1.296769 1.448908 0.086568
+v -1.366609 1.612251 0.076931
+v -1.436448 1.775595 0.067294
+v -1.506288 1.938939 0.057657
+v -1.576127 2.102283 0.048020
+v -1.645967 2.265626 0.038383
+v -1.715806 2.428969 0.028746
+v -1.785645 2.592313 0.019109
+v -1.855485 2.755657 0.009472
+v -1.925324 2.919001 -0.000165
+v -1.995163 3.082345 -0.009802
+v -2.065003 3.245688 -0.019439
+v -2.134842 3.409032 -0.029076
+v -2.204681 3.572375 -0.038713
+v -0.574432 0.211786 0.158062
+v -0.644271 0.375130 0.148426
+v -0.714111 0.538474 0.138788
+v -0.783950 0.701817 0.129151
+v -0.853790 0.865161 0.119514
+v -0.923629 1.028505 0.109877
+v -0.993469 1.191848 0.100240
+v -1.063308 1.355192 0.090603
+v -1.133147 1.518536 0.080966
+v -1.202987 1.681879 0.071329
+v -1.272826 1.845223 0.061692
+v -1.342666 2.008567 0.052055
+v -1.412505 2.171911 0.042418
+v -1.482344 2.335254 0.032781
+v -1.552184 2.498598 0.023144
+v -1.622023 2.661941 0.013507
+v -1.691863 2.825285 0.003870
+v -1.761702 2.988628 -0.005767
+v -1.831541 3.151972 -0.015404
+v -1.901381 3.315316 -0.025041
+v -1.971220 3.478660 -0.034678
+v -2.041059 3.642003 -0.044315
+v -0.340971 0.118071 0.162097
+v -0.410810 0.281414 0.152461
+v -0.480650 0.444758 0.142823
+v -0.550489 0.608102 0.133186
+v -0.620328 0.771445 0.123549
+v -0.690168 0.934789 0.113912
+v -0.760007 1.098133 0.104275
+v -0.829847 1.261476 0.094638
+v -0.899686 1.424820 0.085001
+v -0.969525 1.588164 0.075364
+v -1.039365 1.751507 0.065727
+v -1.109204 1.914851 0.056090
+v -1.179044 2.078194 0.046453
+v -1.248883 2.241538 0.036816
+v -1.318722 2.404882 0.027179
+v -1.388562 2.568226 0.017542
+v -1.458401 2.731569 0.007905
+v -1.528241 2.894913 -0.001732
+v -1.598080 3.058257 -0.011369
+v -1.667919 3.221600 -0.021006
+v -1.737759 3.384944 -0.030643
+v -1.807598 3.548288 -0.040280
+v -1.877437 3.711631 -0.049917
+v -0.107509 0.024355 0.166132
+v -0.177349 0.187698 0.156495
+v -0.247188 0.351042 0.146858
+v -0.317028 0.514386 0.137221
+v -0.386867 0.677729 0.127584
+v -0.456706 0.841073 0.117947
+v -0.526546 1.004417 0.108310
+v -0.596385 1.167760 0.098673
+v -0.666225 1.331104 0.089036
+v -0.736064 1.494448 0.079399
+v -0.805903 1.657791 0.069762
+v -0.875743 1.821135 0.060125
+v -0.945582 1.984479 0.050488
+v -1.015422 2.147822 0.040851
+v -1.085261 2.311166 0.031214
+v -1.155100 2.474510 0.021577
+v -1.224940 2.637853 0.011940
+v -1.294779 2.801197 0.002303
+v -1.364619 2.964541 -0.007334
+v -1.434458 3.127884 -0.016971
+v -1.504297 3.291228 -0.026608
+v -1.574137 3.454572 -0.036245
+v -1.643976 3.617915 -0.045882
+v -1.713815 3.781258 -0.055519
+v 0.125952 -0.069361 0.170167
+v 0.056113 0.093983 0.160530
+v -0.013727 0.257326 0.150893
+v -0.083566 0.420670 0.141256
+v -0.153406 0.584014 0.131619
+v -0.223245 0.747357 0.121982
+v -0.293084 0.910701 0.112345
+v -0.362924 1.074044 0.102708
+v -0.432763 1.237388 0.093071
+v -0.502603 1.400732 0.083434
+v -0.572442 1.564076 0.073797
+v -0.642281 1.727419 0.064160
+v -0.712121 1.890763 0.054523
+v -0.781960 2.054106 0.044886
+v -0.851800 2.217450 0.035249
+v -0.921639 2.380794 0.025612
+v -0.991478 2.544138 0.015975
+v -1.061318 2.707481 0.006338
+v -1.131157 2.870825 -0.003299
+v -1.200997 3.034168 -0.012936
+v -1.270836 3.197512 -0.022573
+v -1.340675 3.360856 -0.032210
+v -1.410515 3.524200 -0.041847
+v -1.480354 3.687543 -0.051485
+v -1.550194 3.850887 -0.061122
+v 0.359413 -0.163077 0.174202
+v 0.289574 0.000267 0.164565
+v 0.219735 0.163610 0.154928
+v 0.149895 0.326954 0.145291
+v 0.080056 0.490298 0.135654
+v 0.010216 0.653641 0.126017
+v -0.059623 0.816985 0.116380
+v -0.129462 0.980329 0.106743
+v -0.199302 1.143672 0.097106
+v -0.269141 1.307016 0.087469
+v -0.338981 1.470360 0.077832
+v -0.408820 1.633703 0.068195
+v -0.478659 1.797047 0.058558
+v -0.548499 1.960391 0.048921
+v -0.618338 2.123734 0.039284
+v -0.688178 2.287078 0.029647
+v -0.758017 2.450422 0.020010
+v -0.827856 2.613765 0.010373
+v -0.897696 2.777109 0.000736
+v -0.967535 2.940452 -0.008901
+v -1.037375 3.103796 -0.018538
+v -1.107214 3.267140 -0.028175
+v -1.177053 3.430484 -0.037812
+v -1.246893 3.593827 -0.047450
+v -1.316732 3.757171 -0.057087
+v -1.386572 3.920515 -0.066724
+v 0.592875 -0.256793 0.178237
+v 0.523035 -0.093449 0.168600
+v 0.453196 0.069894 0.158963
+v 0.383356 0.233238 0.149326
+v 0.313517 0.396582 0.139689
+v 0.243678 0.559926 0.130052
+v 0.173838 0.723269 0.120415
+v 0.103999 0.886613 0.110778
+v 0.034160 1.049956 0.101141
+v -0.035680 1.213300 0.091504
+v -0.105519 1.376644 0.081867
+v -0.175359 1.539987 0.072230
+v -0.245198 1.703331 0.062593
+v -0.315037 1.866675 0.052956
+v -0.384877 2.030019 0.043319
+v -0.454716 2.193362 0.033682
+v -0.524556 2.356706 0.024045
+v -0.594395 2.520050 0.014408
+v -0.664234 2.683393 0.004771
+v -0.734074 2.846737 -0.004866
+v -0.803913 3.010080 -0.014503
+v -0.873753 3.173424 -0.024140
+v -0.943592 3.336768 -0.033778
+v -1.013431 3.500112 -0.043415
+v -1.083271 3.663455 -0.053052
+v -1.153110 3.826799 -0.062689
+v -1.222950 3.990143 -0.072326
+v 0.826336 -0.350509 0.182272
+v 0.756497 -0.187165 0.172635
+v 0.686657 -0.023821 0.162998
+v 0.616818 0.139522 0.153361
+v 0.546978 0.302866 0.143724
+v 0.477139 0.466210 0.134087
+v 0.407299 0.629553 0.124450
+v 0.337460 0.792897 0.114813
+v 0.267621 0.956241 0.105176
+v 0.197781 1.119584 0.095539
+v 0.127942 1.282928 0.085902
+v 0.058103 1.446272 0.076265
+v -0.011737 1.609615 0.066628
+v -0.081576 1.772959 0.056991
+v -0.151416 1.936302 0.047354
+v -0.221255 2.099646 0.037717
+v -0.291094 2.262990 0.028080
+v -0.360934 2.426333 0.018443
+v -0.430773 2.589677 0.008806
+v -0.500613 2.753021 -0.000831
+v -0.570452 2.916364 -0.010468
+v -0.640291 3.079708 -0.020105
+v -0.710131 3.243052 -0.029743
+v -0.779970 3.406395 -0.039380
+v -0.849809 3.569739 -0.049017
+v -0.919649 3.733083 -0.058654
+v -0.989488 3.896427 -0.068291
+v -1.059328 4.059771 -0.077928
+v 1.059797 -0.444224 0.186307
+v 0.989958 -0.280881 0.176670
+v 0.920118 -0.117537 0.167033
+v 0.850279 0.045806 0.157396
+v 0.780440 0.209150 0.147759
+v 0.710600 0.372494 0.138122
+v 0.640761 0.535838 0.128485
+v 0.570921 0.699181 0.118848
+v 0.501082 0.862525 0.109211
+v 0.431243 1.025868 0.099574
+v 0.361403 1.189212 0.089937
+v 0.291564 1.352556 0.080300
+v 0.221724 1.515899 0.070663
+v 0.151885 1.679243 0.061026
+v 0.082046 1.842587 0.051389
+v 0.012206 2.005930 0.041752
+v -0.057633 2.169274 0.032115
+v -0.127473 2.332618 0.022478
+v -0.197312 2.495961 0.012841
+v -0.267151 2.659305 0.003203
+v -0.336991 2.822649 -0.006433
+v -0.406830 2.985992 -0.016070
+v -0.476670 3.149336 -0.025708
+v -0.546509 3.312680 -0.035345
+v -0.616348 3.476023 -0.044982
+v -0.686188 3.639367 -0.054619
+v -0.756027 3.802711 -0.064256
+v -0.825866 3.966055 -0.073893
+v -0.895706 4.129398 -0.083530
+v 1.293259 -0.537940 0.190342
+v 1.223419 -0.374597 0.180705
+v 1.153580 -0.211253 0.171068
+v 1.083740 -0.047909 0.161431
+v 1.013901 0.115434 0.151794
+v 0.944062 0.278778 0.142157
+v 0.874222 0.442122 0.132520
+v 0.804383 0.605465 0.122883
+v 0.734543 0.768809 0.113246
+v 0.664704 0.932153 0.103609
+v 0.594865 1.095496 0.093972
+v 0.525025 1.258840 0.084335
+v 0.455186 1.422184 0.074698
+v 0.385347 1.585527 0.065061
+v 0.315507 1.748871 0.055424
+v 0.245668 1.912214 0.045787
+v 0.175828 2.075558 0.036150
+v 0.105989 2.238902 0.026513
+v 0.036150 2.402245 0.016876
+v -0.033690 2.565589 0.007238
+v -0.103529 2.728933 -0.002398
+v -0.173369 2.892277 -0.012035
+v -0.243208 3.055620 -0.021673
+v -0.313048 3.218964 -0.031310
+v -0.382887 3.382308 -0.040947
+v -0.452726 3.545651 -0.050584
+v -0.522565 3.708995 -0.060221
+v -0.592405 3.872339 -0.069858
+v -0.662244 4.035683 -0.079495
+v -0.732084 4.199026 -0.089132
+v 1.526720 -0.631656 0.194377
+v 1.456881 -0.468312 0.184740
+v 1.387041 -0.304969 0.175103
+v 1.317202 -0.141625 0.165466
+v 1.247363 0.021719 0.155829
+v 1.177523 0.185062 0.146192
+v 1.107684 0.348406 0.136555
+v 1.037845 0.511750 0.126918
+v 0.968005 0.675093 0.117281
+v 0.898166 0.838437 0.107644
+v 0.828327 1.001781 0.098007
+v 0.758487 1.165124 0.088370
+v 0.688648 1.328468 0.078733
+v 0.618808 1.491812 0.069096
+v 0.548969 1.655155 0.059459
+v 0.479130 1.818499 0.049822
+v 0.409290 1.981842 0.040185
+v 0.339451 2.145186 0.030548
+v 0.269611 2.308530 0.020911
+v 0.199772 2.471873 0.011274
+v 0.129933 2.635217 0.001636
+v 0.060093 2.798561 -0.008000
+v -0.009746 2.961904 -0.017638
+v -0.079586 3.125248 -0.027275
+v -0.149425 3.288592 -0.036912
+v -0.219265 3.451936 -0.046549
+v -0.289104 3.615279 -0.056186
+v -0.358943 3.778623 -0.065823
+v -0.428783 3.941966 -0.075460
+v -0.498622 4.105311 -0.085097
+v -0.568462 4.268654 -0.094734
+v 1.760181 -0.725372 0.198412
+v 1.690342 -0.562028 0.188775
+v 1.620502 -0.398685 0.179138
+v 1.550663 -0.235341 0.169501
+v 1.480824 -0.071997 0.159864
+v 1.410985 0.091346 0.150227
+v 1.341145 0.254690 0.140590
+v 1.271306 0.418034 0.130953
+v 1.201466 0.581377 0.121316
+v 1.131627 0.744721 0.111679
+v 1.061788 0.908065 0.102042
+v 0.991948 1.071408 0.092405
+v 0.922109 1.234752 0.082768
+v 0.852270 1.398096 0.073131
+v 0.782430 1.561439 0.063494
+v 0.712591 1.724783 0.053857
+v 0.642752 1.888126 0.044220
+v 0.572912 2.051470 0.034583
+v 0.503073 2.214814 0.024946
+v 0.433233 2.378157 0.015309
+v 0.363394 2.541501 0.005672
+v 0.293555 2.704845 -0.003965
+v 0.223715 2.868189 -0.013603
+v 0.153876 3.031532 -0.023240
+v 0.084036 3.194876 -0.032877
+v 0.014197 3.358220 -0.042514
+v -0.055643 3.521563 -0.052151
+v -0.125482 3.684907 -0.061788
+v -0.195321 3.848251 -0.071425
+v -0.265161 4.011594 -0.081062
+v -0.335000 4.174939 -0.090699
+v -0.404840 4.338282 -0.100336
+v 1.993642 -0.819088 0.202447
+v 1.923803 -0.655744 0.192810
+v 1.853964 -0.492400 0.183173
+v 1.784124 -0.329057 0.173536
+v 1.714285 -0.165713 0.163899
+v 1.644446 -0.002369 0.154262
+v 1.574606 0.160974 0.144625
+v 1.504767 0.324318 0.134988
+v 1.434928 0.487662 0.125351
+v 1.365088 0.651005 0.115714
+v 1.295249 0.814349 0.106077
+v 1.225410 0.977692 0.096440
+v 1.155570 1.141036 0.086803
+v 1.085731 1.304380 0.077166
+v 1.015892 1.467724 0.067529
+v 0.946052 1.631067 0.057892
+v 0.876213 1.794411 0.048255
+v 0.806373 1.957754 0.038618
+v 0.736534 2.121098 0.028981
+v 0.666695 2.284442 0.019344
+v 0.596855 2.447785 0.009706
+v 0.527016 2.611129 0.000069
+v 0.457176 2.774473 -0.009568
+v 0.387337 2.937817 -0.019205
+v 0.317498 3.101161 -0.028842
+v 0.247658 3.264504 -0.038479
+v 0.177819 3.427847 -0.048116
+v 0.107979 3.591191 -0.057753
+v 0.038140 3.754535 -0.067390
+v -0.031699 3.917878 -0.077027
+v -0.101539 4.081222 -0.086664
+v -0.171378 4.244566 -0.096301
+v -0.241217 4.407909 -0.105938
+v 2.227104 -0.912804 0.206482
+v 2.157264 -0.749460 0.196845
+v 2.087425 -0.586116 0.187208
+v 2.017586 -0.422773 0.177571
+v 1.947746 -0.259429 0.167934
+v 1.877907 -0.096085 0.158297
+v 1.808068 0.067258 0.148660
+v 1.738228 0.230602 0.139023
+v 1.668389 0.393946 0.129386
+v 1.598550 0.557289 0.119749
+v 1.528710 0.720633 0.110112
+v 1.458871 0.883977 0.100475
+v 1.389032 1.047320 0.090838
+v 1.319192 1.210664 0.081201
+v 1.249353 1.374008 0.071564
+v 1.179514 1.537351 0.061927
+v 1.109674 1.700695 0.052290
+v 1.039835 1.864038 0.042653
+v 0.969995 2.027382 0.033016
+v 0.900156 2.190726 0.023379
+v 0.830317 2.354070 0.013741
+v 0.760477 2.517413 0.004105
+v 0.690638 2.680757 -0.005533
+v 0.620798 2.844100 -0.015170
+v 0.550959 3.007444 -0.024807
+v 0.481119 3.170788 -0.034444
+v 0.411280 3.334132 -0.044081
+v 0.341441 3.497475 -0.053718
+v 0.271601 3.660819 -0.063355
+v 0.201762 3.824162 -0.072992
+v 0.131922 3.987506 -0.082629
+v 0.062083 4.150850 -0.092266
+v -0.007756 4.314194 -0.101903
+v -0.077596 4.477537 -0.111540
+v 2.460565 -1.006519 0.210517
+v 2.390726 -0.843176 0.200880
+v 2.320886 -0.679832 0.191243
+v 2.251047 -0.516488 0.181606
+v 2.181208 -0.353145 0.171969
+v 2.111368 -0.189801 0.162332
+v 2.041529 -0.026457 0.152695
+v 1.971690 0.136886 0.143058
+v 1.901850 0.300230 0.133421
+v 1.832011 0.463574 0.123784
+v 1.762172 0.626917 0.114147
+v 1.692332 0.790261 0.104510
+v 1.622493 0.953604 0.094873
+v 1.552653 1.116948 0.085236
+v 1.482814 1.280292 0.075599
+v 1.412975 1.443635 0.065962
+v 1.343135 1.606979 0.056325
+v 1.273296 1.770323 0.046688
+v 1.203457 1.933666 0.037051
+v 1.133617 2.097010 0.027414
+v 1.063778 2.260354 0.017776
+v 0.993939 2.423697 0.008140
+v 0.924099 2.587041 -0.001498
+v 0.854260 2.750385 -0.011135
+v 0.784420 2.913728 -0.020772
+v 0.714581 3.077072 -0.030409
+v 0.644741 3.240416 -0.040046
+v 0.574902 3.403759 -0.049683
+v 0.505063 3.567103 -0.059320
+v 0.435223 3.730447 -0.068957
+v 0.365384 3.893790 -0.078594
+v 0.295545 4.057134 -0.088231
+v 0.225705 4.220478 -0.097868
+v 0.155866 4.383822 -0.107505
+v 0.086026 4.547165 -0.117142
+v 2.694026 -1.100235 0.214552
+v 2.624187 -0.936891 0.204915
+v 2.554348 -0.773548 0.195278
+v 2.484508 -0.610204 0.185641
+v 2.414669 -0.446860 0.176004
+v 2.344830 -0.283517 0.166367
+v 2.274990 -0.120173 0.156730
+v 2.205151 0.043171 0.147093
+v 2.135312 0.206514 0.137456
+v 2.065472 0.369858 0.127819
+v 1.995633 0.533202 0.118182
+v 1.925793 0.696545 0.108545
+v 1.855954 0.859889 0.098908
+v 1.786115 1.023233 0.089271
+v 1.716275 1.186576 0.079634
+v 1.646436 1.349920 0.069997
+v 1.576597 1.513264 0.060360
+v 1.506757 1.676607 0.050723
+v 1.436918 1.839951 0.041086
+v 1.367079 2.003294 0.031449
+v 1.297239 2.166638 0.021811
+v 1.227400 2.329982 0.012175
+v 1.157561 2.493325 0.002537
+v 1.087721 2.656669 -0.007100
+v 1.017882 2.820013 -0.016737
+v 0.948043 2.983356 -0.026374
+v 0.878203 3.146700 -0.036011
+v 0.808364 3.310044 -0.045648
+v 0.738524 3.473387 -0.055285
+v 0.668685 3.636731 -0.064922
+v 0.598846 3.800074 -0.074559
+v 0.529006 3.963418 -0.084196
+v 0.459167 4.126763 -0.093833
+v 0.389327 4.290105 -0.103470
+v 0.319488 4.453450 -0.113107
+v 0.249648 4.616793 -0.122744
+v 2.927488 -1.193951 0.218587
+v 2.857649 -1.030607 0.208950
+v 2.787809 -0.867264 0.199313
+v 2.717970 -0.703920 0.189676
+v 2.648130 -0.540576 0.180039
+v 2.578291 -0.377233 0.170402
+v 2.508452 -0.213889 0.160765
+v 2.438612 -0.050545 0.151128
+v 2.368773 0.112799 0.141491
+v 2.298934 0.276142 0.131854
+v 2.229095 0.439486 0.122217
+v 2.159255 0.602829 0.112580
+v 2.089416 0.766173 0.102943
+v 2.019576 0.929517 0.093306
+v 1.949737 1.092860 0.083669
+v 1.879898 1.256204 0.074032
+v 1.810058 1.419548 0.064395
+v 1.740219 1.582891 0.054758
+v 1.670380 1.746235 0.045121
+v 1.600540 1.909578 0.035484
+v 1.530701 2.072922 0.025846
+v 1.460862 2.236266 0.016210
+v 1.391022 2.399609 0.006572
+v 1.321183 2.562953 -0.003065
+v 1.251343 2.726297 -0.012702
+v 1.181504 2.889640 -0.022339
+v 1.111665 3.052984 -0.031976
+v 1.041825 3.216328 -0.041613
+v 0.971986 3.379672 -0.051250
+v 0.902147 3.543015 -0.060887
+v 0.832307 3.706359 -0.070524
+v 0.762468 3.869703 -0.080161
+v 0.692628 4.033046 -0.089798
+v 0.622789 4.196391 -0.099435
+v 0.552949 4.359733 -0.109072
+v 0.483110 4.523077 -0.118709
+v 0.413270 4.686420 -0.128346
+v 3.160949 -1.287667 0.222622
+v 3.091110 -1.124323 0.212985
+v 3.021271 -0.960980 0.203348
+v 2.951431 -0.797636 0.193711
+v 2.881592 -0.634292 0.184074
+v 2.811752 -0.470948 0.174437
+v 2.741913 -0.307605 0.164800
+v 2.672074 -0.144261 0.155163
+v 2.602234 0.019083 0.145526
+v 2.532395 0.182426 0.135889
+v 2.462556 0.345770 0.126252
+v 2.392716 0.509114 0.116615
+v 2.322877 0.672457 0.106978
+v 2.253038 0.835801 0.097341
+v 2.183198 0.999145 0.087704
+v 2.113359 1.162488 0.078067
+v 2.043519 1.325832 0.068430
+v 1.973680 1.489176 0.058793
+v 1.903841 1.652519 0.049156
+v 1.834001 1.815863 0.039519
+v 1.764162 1.979206 0.029881
+v 1.694323 2.142550 0.020245
+v 1.624483 2.305894 0.010607
+v 1.554644 2.469237 0.000970
+v 1.484805 2.632581 -0.008667
+v 1.414965 2.795925 -0.018304
+v 1.345126 2.959268 -0.027941
+v 1.275287 3.122612 -0.037578
+v 1.205447 3.285956 -0.047215
+v 1.135608 3.449299 -0.056852
+v 1.065768 3.612643 -0.066489
+v 0.995929 3.775987 -0.076126
+v 0.926090 3.939330 -0.085763
+v 0.856250 4.102675 -0.095400
+v 0.786411 4.266018 -0.105037
+v 0.716572 4.429361 -0.114674
+v 0.646732 4.592705 -0.124311
+v 0.576893 4.756048 -0.133948
+v 3.394411 -1.381383 0.226657
+v 3.324571 -1.218039 0.217020
+v 3.254732 -1.054695 0.207383
+v 3.184893 -0.891352 0.197746
+v 3.115053 -0.728008 0.188109
+v 3.045214 -0.564664 0.178472
+v 2.975374 -0.401321 0.168835
+v 2.905535 -0.237977 0.159198
+v 2.835696 -0.074633 0.149561
+v 2.765857 0.088711 0.139924
+v 2.696017 0.252054 0.130287
+v 2.626178 0.415398 0.120650
+v 2.556339 0.578741 0.111013
+v 2.486499 0.742085 0.101376
+v 2.416660 0.905429 0.091739
+v 2.346820 1.068772 0.082102
+v 2.276981 1.232116 0.072465
+v 2.207142 1.395460 0.062828
+v 2.137302 1.558803 0.053190
+v 2.067463 1.722147 0.043554
+v 1.997624 1.885490 0.033916
+v 1.927784 2.048834 0.024279
+v 1.857945 2.212178 0.014642
+v 1.788106 2.375521 0.005005
+v 1.718266 2.538865 -0.004632
+v 1.648427 2.702209 -0.014269
+v 1.578587 2.865552 -0.023906
+v 1.508748 3.028896 -0.033543
+v 1.438909 3.192240 -0.043180
+v 1.369069 3.355584 -0.052817
+v 1.299230 3.518927 -0.062454
+v 1.229391 3.682271 -0.072091
+v 1.159551 3.845615 -0.081728
+v 1.089712 4.008958 -0.091365
+v 1.019872 4.172303 -0.101002
+v 0.950033 4.335646 -0.110639
+v 0.880193 4.498990 -0.120276
+v 0.810354 4.662333 -0.129913
+v 0.740515 4.825676 -0.139550
+v 3.627872 -1.475098 0.230692
+v 3.558033 -1.311755 0.221055
+v 3.488194 -1.148411 0.211418
+v 3.418354 -0.985067 0.201781
+v 3.348515 -0.821724 0.192144
+v 3.278676 -0.658380 0.182507
+v 3.208836 -0.495036 0.172870
+v 3.138997 -0.331693 0.163233
+v 3.069157 -0.168349 0.153596
+v 2.999318 -0.005005 0.143959
+v 2.929479 0.158338 0.134322
+v 2.859639 0.321682 0.124685
+v 2.789800 0.485026 0.115048
+v 2.719961 0.648369 0.105411
+v 2.650121 0.811713 0.095774
+v 2.580282 0.975057 0.086137
+v 2.510442 1.138400 0.076500
+v 2.440603 1.301744 0.066863
+v 2.370764 1.465088 0.057225
+v 2.300925 1.628431 0.047589
+v 2.231085 1.791775 0.037951
+v 2.161246 1.955118 0.028314
+v 2.091406 2.118462 0.018677
+v 2.021567 2.281806 0.009040
+v 1.951728 2.445150 -0.000597
+v 1.881888 2.608493 -0.010234
+v 1.812049 2.771837 -0.019871
+v 1.742210 2.935180 -0.029508
+v 1.672370 3.098524 -0.039145
+v 1.602531 3.261868 -0.048782
+v 1.532691 3.425211 -0.058419
+v 1.462852 3.588555 -0.068056
+v 1.393013 3.751899 -0.077693
+v 1.323173 3.915242 -0.087330
+v 1.253334 4.078587 -0.096967
+v 1.183494 4.241930 -0.106604
+v 1.113655 4.405274 -0.116241
+v 1.043816 4.568617 -0.125878
+v 0.973976 4.731961 -0.135515
+v 0.904137 4.895304 -0.145152
+v 3.861333 -1.568815 0.234727
+v 3.791494 -1.405471 0.225090
+v 3.721655 -1.242127 0.215453
+v 3.651815 -1.078783 0.205816
+v 3.581976 -0.915440 0.196179
+v 3.512137 -0.752096 0.186542
+v 3.442297 -0.588752 0.176905
+v 3.372458 -0.425409 0.167268
+v 3.302619 -0.262065 0.157631
+v 3.232779 -0.098721 0.147994
+v 3.162940 0.064623 0.138357
+v 3.093101 0.227966 0.128720
+v 3.023261 0.391310 0.119083
+v 2.953422 0.554654 0.109446
+v 2.883583 0.717997 0.099809
+v 2.813743 0.881341 0.090172
+v 2.743904 1.044684 0.080535
+v 2.674064 1.208028 0.070898
+v 2.604225 1.371372 0.061260
+v 2.534386 1.534715 0.051624
+v 2.464546 1.698059 0.041986
+v 2.394707 1.861402 0.032349
+v 2.324868 2.024746 0.022712
+v 2.255028 2.188090 0.013075
+v 2.185189 2.351433 0.003438
+v 2.115350 2.514777 -0.006199
+v 2.045510 2.678120 -0.015836
+v 1.975671 2.841465 -0.025473
+v 1.905831 3.004808 -0.035110
+v 1.835992 3.168152 -0.044747
+v 1.766153 3.331496 -0.054384
+v 1.696313 3.494839 -0.064021
+v 1.626474 3.658183 -0.073658
+v 1.556635 3.821527 -0.083295
+v 1.486795 3.984870 -0.092932
+v 1.416956 4.148214 -0.102569
+v 1.347116 4.311558 -0.112206
+v 1.277277 4.474902 -0.121843
+v 1.207438 4.638245 -0.131480
+v 1.137598 4.801589 -0.141117
+v 1.067759 4.964931 -0.150754
+v 4.094795 -1.662530 0.238762
+v 4.024956 -1.499186 0.229125
+v 3.955116 -1.335843 0.219488
+v 3.885277 -1.172499 0.209851
+v 3.815438 -1.009155 0.200214
+v 3.745598 -0.845812 0.190577
+v 3.675759 -0.682468 0.180940
+v 3.605919 -0.519124 0.171303
+v 3.536080 -0.355781 0.161666
+v 3.466241 -0.192437 0.152029
+v 3.396401 -0.029093 0.142392
+v 3.326562 0.134250 0.132755
+v 3.256723 0.297594 0.123118
+v 3.186883 0.460938 0.113481
+v 3.117044 0.624281 0.103844
+v 3.047205 0.787625 0.094207
+v 2.977365 0.950969 0.084570
+v 2.907526 1.114312 0.074933
+v 2.837687 1.277656 0.065295
+v 2.767847 1.440999 0.055659
+v 2.698008 1.604343 0.046021
+v 2.628169 1.767687 0.036384
+v 2.558329 1.931030 0.026747
+v 2.488490 2.094374 0.017110
+v 2.418651 2.257718 0.007473
+v 2.348811 2.421061 -0.002164
+v 2.278972 2.584405 -0.011801
+v 2.209132 2.747748 -0.021438
+v 2.139293 2.911092 -0.031075
+v 2.069454 3.074436 -0.040712
+v 1.999614 3.237780 -0.050349
+v 1.929775 3.401124 -0.059986
+v 1.859936 3.564467 -0.069623
+v 1.790096 3.727811 -0.079260
+v 1.720257 3.891155 -0.088897
+v 1.650417 4.054498 -0.098534
+v 1.580578 4.217842 -0.108171
+v 1.510738 4.381186 -0.117808
+v 1.440899 4.544529 -0.127445
+v 1.371060 4.707873 -0.137082
+v 1.301220 4.871216 -0.146720
+v 1.231381 5.034559 -0.156357
+v 4.328257 -1.756246 0.242797
+v 4.258417 -1.592903 0.233160
+v 4.188578 -1.429559 0.223523
+v 4.118738 -1.266215 0.213886
+v 4.048899 -1.102871 0.204249
+v 3.979060 -0.939528 0.194612
+v 3.909220 -0.776184 0.184975
+v 3.839381 -0.612840 0.175338
+v 3.769542 -0.449497 0.165701
+v 3.699702 -0.286153 0.156064
+v 3.629863 -0.122809 0.146427
+v 3.560024 0.040535 0.136790
+v 3.490184 0.203878 0.127153
+v 3.420345 0.367222 0.117516
+v 3.350505 0.530566 0.107879
+v 3.280666 0.693909 0.098242
+v 3.210827 0.857253 0.088605
+v 3.140987 1.020596 0.078968
+v 3.071148 1.183940 0.069330
+v 3.001309 1.347284 0.059694
+v 2.931469 1.510627 0.050056
+v 2.861630 1.673971 0.040419
+v 2.791791 1.837314 0.030782
+v 2.721951 2.000658 0.021145
+v 2.652112 2.164002 0.011508
+v 2.582273 2.327345 0.001871
+v 2.512433 2.490689 -0.007766
+v 2.442594 2.654033 -0.017403
+v 2.372755 2.817376 -0.027040
+v 2.302915 2.980720 -0.036677
+v 2.233076 3.144064 -0.046314
+v 2.163237 3.307407 -0.055951
+v 2.093397 3.470751 -0.065588
+v 2.023558 3.634095 -0.075225
+v 1.953718 3.797439 -0.084862
+v 1.883879 3.960782 -0.094499
+v 1.814040 4.124126 -0.104136
+v 1.744200 4.287470 -0.113773
+v 1.674361 4.450814 -0.123410
+v 1.604521 4.614157 -0.133048
+v 1.534682 4.777501 -0.142685
+v 1.464842 4.940844 -0.152322
+v 1.395003 5.104187 -0.161959
+v 4.561718 -1.849962 0.246832
+v 4.491879 -1.686618 0.237195
+v 4.422039 -1.523275 0.227558
+v 4.352200 -1.359931 0.217921
+v 4.282360 -1.196587 0.208284
+v 4.212521 -1.033243 0.198647
+v 4.142681 -0.869900 0.189010
+v 4.072842 -0.706556 0.179373
+v 4.003003 -0.543212 0.169736
+v 3.933163 -0.379869 0.160099
+v 3.863324 -0.216525 0.150462
+v 3.793484 -0.053181 0.140825
+v 3.723645 0.110162 0.131188
+v 3.653806 0.273506 0.121551
+v 3.583966 0.436850 0.111914
+v 3.514127 0.600194 0.102277
+v 3.444288 0.763537 0.092639
+v 3.374448 0.926881 0.083003
+v 3.304609 1.090224 0.073365
+v 3.234770 1.253568 0.063729
+v 3.164930 1.416912 0.054091
+v 3.095091 1.580255 0.044454
+v 3.025252 1.743599 0.034817
+v 2.955412 1.906943 0.025180
+v 2.885573 2.070286 0.015543
+v 2.815734 2.233629 0.005906
+v 2.745894 2.396973 -0.003731
+v 2.676055 2.560317 -0.013368
+v 2.606216 2.723661 -0.023005
+v 2.536376 2.887004 -0.032642
+v 2.466537 3.050348 -0.042279
+v 2.396698 3.213691 -0.051916
+v 2.326858 3.377035 -0.061553
+v 2.257019 3.540379 -0.071190
+v 2.187180 3.703722 -0.080827
+v 2.117340 3.867067 -0.090464
+v 2.047501 4.030410 -0.100101
+v 1.977661 4.193754 -0.109738
+v 1.907822 4.357098 -0.119375
+v 1.837982 4.520442 -0.129013
+v 1.768143 4.683785 -0.138650
+v 1.698304 4.847129 -0.148287
+v 1.628464 5.010472 -0.157924
+v 1.558625 5.173815 -0.167561
+v 4.795178 -1.943678 0.250867
+v 4.725339 -1.780334 0.241230
+v 4.655500 -1.616990 0.231593
+v 4.585661 -1.453647 0.221956
+v 4.515821 -1.290303 0.212319
+v 4.445982 -1.126959 0.202682
+v 4.376143 -0.963615 0.193045
+v 4.306303 -0.800272 0.183408
+v 4.236464 -0.636928 0.173771
+v 4.166625 -0.473584 0.164134
+v 4.096786 -0.310241 0.154497
+v 4.026946 -0.146897 0.144860
+v 3.957106 0.016446 0.135223
+v 3.887267 0.179790 0.125586
+v 3.817428 0.343134 0.115949
+v 3.747588 0.506478 0.106312
+v 3.677749 0.669821 0.096674
+v 3.607910 0.833165 0.087038
+v 3.538070 0.996508 0.077400
+v 3.468231 1.159852 0.067763
+v 3.398391 1.323196 0.058126
+v 3.328552 1.486539 0.048489
+v 3.258713 1.649883 0.038852
+v 3.188874 1.813227 0.029215
+v 3.119034 1.976570 0.019578
+v 3.049195 2.139914 0.009941
+v 2.979356 2.303257 0.000304
+v 2.909516 2.466601 -0.009333
+v 2.839677 2.629944 -0.018970
+v 2.769838 2.793288 -0.028607
+v 2.699998 2.956631 -0.038244
+v 2.630159 3.119976 -0.047881
+v 2.560319 3.283319 -0.057518
+v 2.490480 3.446663 -0.067155
+v 2.420641 3.610007 -0.076792
+v 2.350801 3.773350 -0.086429
+v 2.280962 3.936694 -0.096066
+v 2.211123 4.100038 -0.105703
+v 2.141283 4.263381 -0.115340
+v 2.071444 4.426725 -0.124978
+v 2.001605 4.590069 -0.134615
+v 1.931765 4.753413 -0.144252
+v 1.861926 4.916757 -0.153889
+v 1.792086 5.080100 -0.163526
+v 1.722247 5.243443 -0.173163
+v 5.028641 -2.037393 0.254902
+v 4.958801 -1.874050 0.245265
+v 4.888962 -1.710706 0.235628
+v 4.819122 -1.547362 0.225991
+v 4.749283 -1.384019 0.216354
+v 4.679443 -1.220675 0.206717
+v 4.609604 -1.057331 0.197080
+v 4.539764 -0.893988 0.187443
+v 4.469925 -0.730644 0.177806
+v 4.400086 -0.567300 0.168169
+v 4.330247 -0.403957 0.158532
+v 4.260407 -0.240613 0.148895
+v 4.190568 -0.077269 0.139258
+v 4.120728 0.086074 0.129621
+v 4.050889 0.249418 0.119984
+v 3.981050 0.412762 0.110347
+v 3.911211 0.576105 0.100709
+v 3.841371 0.739449 0.091073
+v 3.771532 0.902793 0.081435
+v 3.701692 1.066136 0.071798
+v 3.631853 1.229480 0.062161
+v 3.562014 1.392824 0.052524
+v 3.492174 1.556167 0.042887
+v 3.422335 1.719511 0.033250
+v 3.352496 1.882854 0.023613
+v 3.282656 2.046198 0.013976
+v 3.212817 2.209542 0.004339
+v 3.142978 2.372885 -0.005298
+v 3.073138 2.536229 -0.014935
+v 3.003299 2.699573 -0.024572
+v 2.933460 2.862916 -0.034209
+v 2.863620 3.026260 -0.043846
+v 2.793781 3.189603 -0.053483
+v 2.723942 3.352947 -0.063120
+v 2.654102 3.516291 -0.072757
+v 2.584263 3.679635 -0.082394
+v 2.514423 3.842979 -0.092031
+v 2.444584 4.006322 -0.101668
+v 2.374745 4.169666 -0.111305
+v 2.304905 4.333009 -0.120943
+v 2.235066 4.496353 -0.130580
+v 2.165227 4.659697 -0.140217
+v 2.095387 4.823040 -0.149854
+v 2.025548 4.986385 -0.159491
+v 1.955708 5.149727 -0.169128
+v 1.885869 5.313070 -0.178765
+v 5.262101 -2.131109 0.258937
+v 5.192262 -1.967766 0.249300
+v 5.122422 -1.804422 0.239663
+v 5.052583 -1.641078 0.230026
+v 4.982744 -1.477734 0.220389
+v 4.912905 -1.314391 0.210752
+v 4.843065 -1.151047 0.201115
+v 4.773226 -0.987703 0.191478
+v 4.703386 -0.824360 0.181841
+v 4.633547 -0.661016 0.172204
+v 4.563707 -0.497672 0.162567
+v 4.493869 -0.334329 0.152930
+v 4.424029 -0.170985 0.143293
+v 4.354190 -0.007642 0.133656
+v 4.284350 0.155702 0.124019
+v 4.214511 0.319046 0.114382
+v 4.144671 0.482390 0.104744
+v 4.074832 0.645733 0.095108
+v 4.004992 0.809077 0.085470
+v 3.935153 0.972420 0.075833
+v 3.865314 1.135764 0.066196
+v 3.795475 1.299108 0.056559
+v 3.725635 1.462451 0.046922
+v 3.655796 1.625795 0.037285
+v 3.585957 1.789138 0.027648
+v 3.516117 1.952482 0.018011
+v 3.446278 2.115826 0.008374
+v 3.376439 2.279169 -0.001263
+v 3.306599 2.442513 -0.010900
+v 3.236760 2.605856 -0.020537
+v 3.166921 2.769200 -0.030174
+v 3.097081 2.932544 -0.039811
+v 3.027242 3.095887 -0.049448
+v 2.957403 3.259231 -0.059085
+v 2.887563 3.422575 -0.068722
+v 2.817724 3.585918 -0.078359
+v 2.747885 3.749262 -0.087996
+v 2.678045 3.912606 -0.097633
+v 2.608206 4.075950 -0.107270
+v 2.538366 4.239294 -0.116908
+v 2.468527 4.402637 -0.126545
+v 2.398688 4.565981 -0.136182
+v 2.328848 4.729325 -0.145819
+v 2.259009 4.892668 -0.155456
+v 2.189170 5.056013 -0.165093
+v 2.119330 5.219355 -0.174730
+v 2.049491 5.382698 -0.184367
+v 5.495563 -2.224826 0.262972
+v 5.425723 -2.061481 0.253335
+v 5.355885 -1.898138 0.243698
+v 5.286045 -1.734794 0.234061
+v 5.216206 -1.571451 0.224424
+v 5.146366 -1.408107 0.214787
+v 5.076527 -1.244763 0.205150
+v 5.006687 -1.081420 0.195513
+v 4.936848 -0.918076 0.185876
+v 4.867008 -0.754732 0.176239
+v 4.797169 -0.591388 0.166602
+v 4.727330 -0.428045 0.156965
+v 4.657491 -0.264701 0.147328
+v 4.587651 -0.101357 0.137691
+v 4.517812 0.061986 0.128054
+v 4.447972 0.225330 0.118417
+v 4.378133 0.388674 0.108779
+v 4.308293 0.552017 0.099143
+v 4.238455 0.715361 0.089505
+v 4.168615 0.878705 0.079868
+v 4.098776 1.042048 0.070231
+v 4.028936 1.205392 0.060594
+v 3.959097 1.368735 0.050957
+v 3.889257 1.532079 0.041320
+v 3.819418 1.695423 0.031683
+v 3.749579 1.858766 0.022046
+v 3.679739 2.022110 0.012409
+v 3.609900 2.185454 0.002772
+v 3.540061 2.348797 -0.006865
+v 3.470222 2.512141 -0.016502
+v 3.400382 2.675484 -0.026139
+v 3.330543 2.838828 -0.035776
+v 3.260704 3.002172 -0.045413
+v 3.190864 3.165515 -0.055050
+v 3.121025 3.328859 -0.064687
+v 3.051185 3.492203 -0.074324
+v 2.981346 3.655546 -0.083961
+v 2.911507 3.818890 -0.093598
+v 2.841667 3.982234 -0.103236
+v 2.771828 4.145578 -0.112873
+v 2.701989 4.308921 -0.122510
+v 2.632149 4.472265 -0.132147
+v 2.562310 4.635609 -0.141784
+v 2.492471 4.798953 -0.151421
+v 2.422631 4.962296 -0.161058
+v 2.352792 5.125640 -0.170695
+v 2.282953 5.288983 -0.180332
+v 2.213113 5.452327 -0.189969
+v 5.729023 -2.318541 0.267007
+v 5.659184 -2.155197 0.257370
+v 5.589345 -1.991854 0.247733
+v 5.519506 -1.828510 0.238096
+v 5.449666 -1.665166 0.228459
+v 5.379827 -1.501822 0.218822
+v 5.309987 -1.338479 0.209185
+v 5.240148 -1.175135 0.199548
+v 5.170308 -1.011791 0.189911
+v 5.100470 -0.848448 0.180274
+v 5.030630 -0.685104 0.170637
+v 4.960791 -0.521760 0.161000
+v 4.890951 -0.358416 0.151363
+v 4.821112 -0.195073 0.141726
+v 4.751272 -0.031729 0.132089
+v 4.681433 0.131614 0.122452
+v 4.611594 0.294958 0.112814
+v 4.541755 0.458302 0.103178
+v 4.471915 0.621645 0.093540
+v 4.402076 0.784989 0.083903
+v 4.332236 0.948332 0.074266
+v 4.262397 1.111676 0.064629
+v 4.192557 1.275020 0.054992
+v 4.122719 1.438363 0.045355
+v 4.052879 1.601707 0.035718
+v 3.983040 1.765051 0.026081
+v 3.913200 1.928394 0.016444
+v 3.843361 2.091738 0.006807
+v 3.773521 2.255081 -0.002830
+v 3.703682 2.418425 -0.012467
+v 3.633843 2.581769 -0.022104
+v 3.564003 2.745112 -0.031741
+v 3.494164 2.908456 -0.041378
+v 3.424325 3.071799 -0.051015
+v 3.354486 3.235143 -0.060652
+v 3.284646 3.398487 -0.070289
+v 3.214807 3.561830 -0.079926
+v 3.144968 3.725174 -0.089563
+v 3.075128 3.888518 -0.099200
+v 3.005289 4.051861 -0.108838
+v 2.935449 4.215206 -0.118475
+v 2.865610 4.378549 -0.128112
+v 2.795771 4.541893 -0.137749
+v 2.725931 4.705236 -0.147386
+v 2.656092 4.868580 -0.157023
+v 2.586253 5.031924 -0.166660
+v 2.516413 5.195268 -0.176297
+v 2.446574 5.358611 -0.185934
+v 2.376735 5.521955 -0.195571
+v -2.218616 -5.893647 0.551145
+v -2.054993 -5.824019 0.545543
+v -2.288455 -5.730304 0.541508
+v -1.891371 -5.754392 0.539941
+v -2.124833 -5.660676 0.535906
+v -2.358294 -5.566959 0.531871
+v -1.727749 -5.684764 0.534339
+v -1.961210 -5.591048 0.530304
+v -2.194672 -5.497332 0.526269
+v -2.428133 -5.403617 0.522234
+v -1.564127 -5.615136 0.528737
+v -1.797588 -5.521420 0.524702
+v -2.031050 -5.427704 0.520667
+v -2.264511 -5.333989 0.516632
+v -2.497972 -5.240272 0.512597
+v -1.400505 -5.545508 0.523135
+v -1.633966 -5.451793 0.519100
+v -1.867428 -5.358076 0.515065
+v -2.100889 -5.264361 0.511030
+v -2.334351 -5.170644 0.506995
+v -2.567812 -5.076930 0.502960
+v -1.236883 -5.475881 0.517533
+v -1.470344 -5.382164 0.513498
+v -1.703806 -5.288448 0.509463
+v -1.937267 -5.194733 0.505428
+v -2.170728 -5.101017 0.501393
+v -2.404190 -5.007302 0.497358
+v -2.637651 -4.913586 0.493323
+v -1.073261 -5.406252 0.511930
+v -1.306722 -5.312536 0.507895
+v -1.540184 -5.218821 0.503860
+v -1.773645 -5.125105 0.499825
+v -2.007106 -5.031389 0.495791
+v -2.240568 -4.937673 0.491756
+v -2.474029 -4.843958 0.487721
+v -2.707490 -4.750243 0.483686
+v -0.909639 -5.336624 0.506329
+v -1.143100 -5.242908 0.502294
+v -1.376562 -5.149193 0.498259
+v -1.610023 -5.055477 0.494224
+v -1.843484 -4.961761 0.490189
+v -2.076945 -4.868045 0.486154
+v -2.310407 -4.774330 0.482119
+v -2.543869 -4.680614 0.478084
+v -2.777330 -4.586899 0.474049
+v -0.746017 -5.266996 0.500726
+v -0.979478 -5.173281 0.496691
+v -1.212940 -5.079565 0.492656
+v -1.446401 -4.985850 0.488621
+v -1.679862 -4.892134 0.484586
+v -1.913324 -4.798418 0.480551
+v -2.146785 -4.704702 0.476516
+v -2.380247 -4.610986 0.472481
+v -2.613708 -4.517271 0.468446
+v -2.847169 -4.423555 0.464411
+v -0.582395 -5.197369 0.495124
+v -0.815856 -5.103653 0.491089
+v -1.049317 -5.009937 0.487054
+v -1.282779 -4.916221 0.483019
+v -1.516240 -4.822505 0.478984
+v -1.749701 -4.728789 0.474949
+v -1.983163 -4.635074 0.470914
+v -2.216624 -4.541358 0.466880
+v -2.450086 -4.447642 0.462845
+v -2.683547 -4.353927 0.458810
+v -2.917009 -4.260211 0.454775
+v -0.418772 -5.127741 0.489522
+v -0.652234 -5.034025 0.485487
+v -0.885695 -4.940310 0.481452
+v -1.119157 -4.846593 0.477417
+v -1.352618 -4.752878 0.473382
+v -1.586080 -4.659162 0.469347
+v -1.819541 -4.565446 0.465312
+v -2.053002 -4.471730 0.461277
+v -2.286463 -4.378014 0.457242
+v -2.519925 -4.284298 0.453207
+v -2.753386 -4.190583 0.449172
+v -2.986848 -4.096868 0.445138
+v -0.255151 -5.058113 0.483920
+v -0.488612 -4.964397 0.479885
+v -0.722073 -4.870682 0.475850
+v -0.955535 -4.776966 0.471815
+v -1.188996 -4.683250 0.467780
+v -1.422458 -4.589534 0.463745
+v -1.655919 -4.495819 0.459710
+v -1.889380 -4.402102 0.455675
+v -2.122842 -4.308386 0.451640
+v -2.356303 -4.214671 0.447605
+v -2.589765 -4.120955 0.443570
+v -2.823226 -4.027239 0.439535
+v -3.056687 -3.933524 0.435500
+v -0.091529 -4.988485 0.478318
+v -0.324990 -4.894770 0.474283
+v -0.558451 -4.801054 0.470248
+v -0.791913 -4.707338 0.466213
+v -1.025374 -4.613622 0.462178
+v -1.258836 -4.519907 0.458143
+v -1.492297 -4.426191 0.454108
+v -1.725758 -4.332475 0.450073
+v -1.959220 -4.238759 0.446038
+v -2.192681 -4.145043 0.442003
+v -2.426142 -4.051328 0.437968
+v -2.659604 -3.957612 0.433933
+v -2.893065 -3.863896 0.429899
+v -3.126527 -3.770180 0.425864
+v 0.072093 -4.918858 0.472716
+v -0.161368 -4.825142 0.468681
+v -0.394830 -4.731426 0.464646
+v -0.628291 -4.637710 0.460611
+v -0.861752 -4.543994 0.456576
+v -1.095214 -4.450279 0.452541
+v -1.328675 -4.356562 0.448506
+v -1.562136 -4.262847 0.444471
+v -1.795598 -4.169131 0.440436
+v -2.029059 -4.075416 0.436401
+v -2.262521 -3.981699 0.432366
+v -2.495982 -3.887984 0.428331
+v -2.729443 -3.794269 0.424296
+v -2.962905 -3.700552 0.420261
+v -3.196366 -3.606837 0.416226
+v 0.235715 -4.849230 0.467114
+v 0.002254 -4.755514 0.463079
+v -0.231208 -4.661798 0.459044
+v -0.464669 -4.568082 0.455009
+v -0.698130 -4.474367 0.450974
+v -0.931592 -4.380651 0.446939
+v -1.165053 -4.286934 0.442904
+v -1.398514 -4.193219 0.438869
+v -1.631976 -4.099504 0.434834
+v -1.865437 -4.005788 0.430799
+v -2.098898 -3.912072 0.426764
+v -2.332360 -3.818356 0.422729
+v -2.565821 -3.724640 0.418694
+v -2.799283 -3.630925 0.414659
+v -3.032744 -3.537209 0.410624
+v -3.266205 -3.443493 0.406589
+v 0.399337 -4.779602 0.461512
+v 0.165876 -4.685886 0.457477
+v -0.067586 -4.592171 0.453442
+v -0.301047 -4.498455 0.449407
+v -0.534508 -4.404739 0.445372
+v -0.767970 -4.311023 0.441337
+v -1.001431 -4.217307 0.437302
+v -1.234892 -4.123591 0.433267
+v -1.468354 -4.029876 0.429232
+v -1.701815 -3.936160 0.425197
+v -1.935277 -3.842444 0.421162
+v -2.168738 -3.748729 0.417127
+v -2.402199 -3.655013 0.413092
+v -2.635661 -3.561297 0.409057
+v -2.869122 -3.467582 0.405022
+v -3.102583 -3.373866 0.400987
+v -3.336045 -3.280150 0.396952
+v 0.562959 -4.709974 0.455910
+v 0.329498 -4.616258 0.451875
+v 0.096036 -4.522543 0.447840
+v -0.137425 -4.428827 0.443805
+v -0.370887 -4.335111 0.439770
+v -0.604348 -4.241395 0.435735
+v -0.837809 -4.147679 0.431700
+v -1.071271 -4.053964 0.427665
+v -1.304732 -3.960248 0.423630
+v -1.538193 -3.866532 0.419595
+v -1.771655 -3.772816 0.415560
+v -2.005116 -3.679101 0.411525
+v -2.238577 -3.585385 0.407490
+v -2.472039 -3.491669 0.403455
+v -2.705500 -3.397954 0.399420
+v -2.938962 -3.304238 0.395385
+v -3.172423 -3.210522 0.391350
+v -3.405884 -3.116806 0.387315
+v 0.726581 -4.640347 0.450308
+v 0.493120 -4.546630 0.446273
+v 0.259658 -4.452915 0.442238
+v 0.026197 -4.359199 0.438203
+v -0.207264 -4.265483 0.434168
+v -0.440726 -4.171768 0.430133
+v -0.674187 -4.078052 0.426098
+v -0.907648 -3.984335 0.422063
+v -1.141110 -3.890620 0.418028
+v -1.374571 -3.796905 0.413993
+v -1.608033 -3.703188 0.409958
+v -1.841494 -3.609473 0.405923
+v -2.074955 -3.515757 0.401888
+v -2.308417 -3.422041 0.397853
+v -2.541878 -3.328326 0.393818
+v -2.775339 -3.234610 0.389783
+v -3.008801 -3.140894 0.385748
+v -3.242262 -3.047179 0.381713
+v -3.475723 -2.953463 0.377678
+v 0.890203 -4.570719 0.444706
+v 0.656742 -4.477002 0.440671
+v 0.423280 -4.383287 0.436636
+v 0.189819 -4.289571 0.432601
+v -0.043642 -4.195856 0.428566
+v -0.277104 -4.102139 0.424531
+v -0.510565 -4.008424 0.420496
+v -0.744026 -3.914708 0.416461
+v -0.977488 -3.820992 0.412426
+v -1.210949 -3.727276 0.408391
+v -1.444410 -3.633561 0.404356
+v -1.677872 -3.539845 0.400321
+v -1.911333 -3.446129 0.396286
+v -2.144794 -3.352414 0.392251
+v -2.378256 -3.258698 0.388216
+v -2.611717 -3.164982 0.384181
+v -2.845179 -3.071266 0.380146
+v -3.078640 -2.977550 0.376111
+v -3.312101 -2.883835 0.372076
+v -3.545563 -2.790119 0.368041
+v 1.053825 -4.501091 0.439104
+v 0.820364 -4.407374 0.435069
+v 0.586903 -4.313660 0.431034
+v 0.353441 -4.219944 0.426999
+v 0.119980 -4.126228 0.422964
+v -0.113482 -4.032512 0.418929
+v -0.346943 -3.938796 0.414894
+v -0.580405 -3.845080 0.410859
+v -0.813866 -3.751364 0.406824
+v -1.047327 -3.657649 0.402789
+v -1.280789 -3.563933 0.398754
+v -1.514250 -3.470217 0.394719
+v -1.747711 -3.376501 0.390684
+v -1.981173 -3.282785 0.386649
+v -2.214634 -3.189070 0.382614
+v -2.448095 -3.095354 0.378579
+v -2.681557 -3.001638 0.374544
+v -2.915018 -2.907923 0.370509
+v -3.148480 -2.814207 0.366474
+v -3.381941 -2.720491 0.362439
+v -3.615402 -2.626775 0.358404
+v 1.217447 -4.431463 0.433502
+v 0.983986 -4.337747 0.429467
+v 0.750524 -4.244032 0.425432
+v 0.517063 -4.150316 0.421397
+v 0.283602 -4.056600 0.417362
+v 0.050140 -3.962884 0.413327
+v -0.183321 -3.869168 0.409292
+v -0.416783 -3.775452 0.405257
+v -0.650244 -3.681736 0.401222
+v -0.883705 -3.588021 0.397187
+v -1.117167 -3.494305 0.393152
+v -1.350628 -3.400589 0.389117
+v -1.584089 -3.306873 0.385082
+v -1.817551 -3.213157 0.381047
+v -2.051012 -3.119442 0.377012
+v -2.284473 -3.025727 0.372977
+v -2.517935 -2.932010 0.368942
+v -2.751396 -2.838295 0.364907
+v -2.984857 -2.744579 0.360872
+v -3.218319 -2.650863 0.356837
+v -3.451780 -2.557148 0.352802
+v -3.685241 -2.463431 0.348767
+v 1.381069 -4.361835 0.427900
+v 1.147608 -4.268119 0.423865
+v 0.914147 -4.174404 0.419830
+v 0.680685 -4.080688 0.415795
+v 0.447224 -3.986972 0.411760
+v 0.213762 -3.893256 0.407725
+v -0.019699 -3.799540 0.403690
+v -0.253161 -3.705824 0.399655
+v -0.486622 -3.612109 0.395620
+v -0.720084 -3.518393 0.391585
+v -0.953545 -3.424677 0.387550
+v -1.187006 -3.330961 0.383515
+v -1.420467 -3.237246 0.379480
+v -1.653929 -3.143530 0.375445
+v -1.887390 -3.049814 0.371410
+v -2.120852 -2.956098 0.367375
+v -2.354313 -2.862382 0.363340
+v -2.587774 -2.768667 0.359305
+v -2.821235 -2.674951 0.355270
+v -3.054697 -2.581235 0.351235
+v -3.288158 -2.487519 0.347200
+v -3.521620 -2.393804 0.343165
+v -3.755081 -2.300088 0.339130
+v 1.544691 -4.292208 0.422298
+v 1.311230 -4.198491 0.418263
+v 1.077768 -4.104776 0.414228
+v 0.844307 -4.011060 0.410193
+v 0.610846 -3.917344 0.406158
+v 0.377384 -3.823628 0.402123
+v 0.143923 -3.729912 0.398088
+v -0.089539 -3.636197 0.394053
+v -0.323000 -3.542481 0.390018
+v -0.556461 -3.448765 0.385983
+v -0.789923 -3.355049 0.381948
+v -1.023384 -3.261333 0.377913
+v -1.256845 -3.167618 0.373878
+v -1.490307 -3.073902 0.369843
+v -1.723768 -2.980186 0.365808
+v -1.957229 -2.886470 0.361773
+v -2.190691 -2.792754 0.357738
+v -2.424152 -2.699039 0.353703
+v -2.657614 -2.605323 0.349668
+v -2.891075 -2.511607 0.345633
+v -3.124536 -2.417892 0.341598
+v -3.357998 -2.324176 0.337563
+v -3.591459 -2.230460 0.333528
+v -3.824920 -2.136744 0.329493
+v 1.708313 -4.222580 0.416696
+v 1.474852 -4.128863 0.412661
+v 1.241390 -4.035148 0.408626
+v 1.007929 -3.941432 0.404591
+v 0.774468 -3.847716 0.400556
+v 0.541006 -3.754000 0.396521
+v 0.307545 -3.660285 0.392486
+v 0.074084 -3.566569 0.388451
+v -0.159378 -3.472853 0.384416
+v -0.392839 -3.379137 0.380381
+v -0.626301 -3.285421 0.376346
+v -0.859762 -3.191705 0.372311
+v -1.093223 -3.097989 0.368276
+v -1.326685 -3.004274 0.364241
+v -1.560146 -2.910558 0.360206
+v -1.793607 -2.816843 0.356171
+v -2.027069 -2.723127 0.352136
+v -2.260530 -2.629411 0.348101
+v -2.493991 -2.535695 0.344066
+v -2.727453 -2.441979 0.340031
+v -2.960914 -2.348264 0.335996
+v -3.194375 -2.254548 0.331961
+v -3.427837 -2.160832 0.327926
+v -3.661298 -2.067116 0.323891
+v -3.894759 -1.973400 0.319856
+v 1.871935 -4.152952 0.411094
+v 1.638474 -4.059236 0.407059
+v 1.405012 -3.965520 0.403024
+v 1.171551 -3.871805 0.398989
+v 0.938090 -3.778089 0.394954
+v 0.704628 -3.684372 0.390919
+v 0.471167 -3.590657 0.386884
+v 0.237706 -3.496941 0.382849
+v 0.004244 -3.403225 0.378814
+v -0.229217 -3.309509 0.374779
+v -0.462679 -3.215794 0.370744
+v -0.696140 -3.122078 0.366709
+v -0.929602 -3.028362 0.362674
+v -1.163063 -2.934646 0.358639
+v -1.396524 -2.840931 0.354604
+v -1.629985 -2.747215 0.350569
+v -1.863447 -2.653499 0.346534
+v -2.096908 -2.559783 0.342499
+v -2.330369 -2.466068 0.338464
+v -2.563831 -2.372352 0.334429
+v -2.797292 -2.278636 0.330394
+v -3.030753 -2.184920 0.326359
+v -3.264215 -2.091204 0.322324
+v -3.497676 -1.997488 0.318289
+v -3.731138 -1.903773 0.314254
+v -3.964599 -1.810057 0.310219
+v 2.035557 -4.083324 0.405492
+v 1.802096 -3.989609 0.401457
+v 1.568634 -3.895892 0.397422
+v 1.335173 -3.802177 0.393387
+v 1.101712 -3.708461 0.389352
+v 0.868250 -3.614745 0.385317
+v 0.634789 -3.521029 0.381282
+v 0.401328 -3.427313 0.377247
+v 0.167866 -3.333597 0.373212
+v -0.065595 -3.239882 0.369177
+v -0.299057 -3.146165 0.365142
+v -0.532518 -3.052450 0.361107
+v -0.765979 -2.958734 0.357072
+v -0.999441 -2.865018 0.353036
+v -1.232902 -2.771303 0.349001
+v -1.466363 -2.677587 0.344966
+v -1.699825 -2.583871 0.340932
+v -1.933286 -2.490155 0.336897
+v -2.166747 -2.396440 0.332862
+v -2.400209 -2.302724 0.328827
+v -2.633670 -2.209008 0.324792
+v -2.867131 -2.115292 0.320757
+v -3.100593 -2.021576 0.316722
+v -3.334054 -1.927860 0.312687
+v -3.567516 -1.834145 0.308652
+v -3.800977 -1.740429 0.304617
+v -4.034438 -1.646713 0.300582
+v 2.199179 -4.013697 0.399889
+v 1.965718 -3.919981 0.395854
+v 1.732256 -3.826265 0.391819
+v 1.498795 -3.732549 0.387784
+v 1.265334 -3.638833 0.383749
+v 1.031872 -3.545117 0.379714
+v 0.798411 -3.451401 0.375679
+v 0.564950 -3.357686 0.371644
+v 0.331488 -3.263969 0.367610
+v 0.098027 -3.170254 0.363575
+v -0.135435 -3.076538 0.359540
+v -0.368896 -2.982822 0.355505
+v -0.602357 -2.889106 0.351470
+v -0.835819 -2.795390 0.347435
+v -1.069280 -2.701675 0.343400
+v -1.302741 -2.607959 0.339365
+v -1.536203 -2.514243 0.335330
+v -1.769664 -2.420527 0.331295
+v -2.003125 -2.326812 0.327260
+v -2.236587 -2.233096 0.323225
+v -2.470048 -2.139380 0.319190
+v -2.703509 -2.045664 0.315155
+v -2.936971 -1.951948 0.311120
+v -3.170432 -1.858232 0.307085
+v -3.403893 -1.764517 0.303050
+v -3.637355 -1.670801 0.299015
+v -3.870816 -1.577085 0.294980
+v -4.104278 -1.483369 0.290945
+v 2.362801 -3.944069 0.394287
+v 2.129340 -3.850353 0.390253
+v 1.895878 -3.756637 0.386218
+v 1.662417 -3.662921 0.382183
+v 1.428956 -3.569205 0.378148
+v 1.195494 -3.475489 0.374113
+v 0.962033 -3.381773 0.370078
+v 0.728572 -3.288058 0.366043
+v 0.495110 -3.194342 0.362008
+v 0.261649 -3.100626 0.357973
+v 0.028187 -3.006910 0.353938
+v -0.205274 -2.913194 0.349903
+v -0.438735 -2.819478 0.345867
+v -0.672197 -2.725763 0.341832
+v -0.905658 -2.632047 0.337797
+v -1.139120 -2.538331 0.333762
+v -1.372581 -2.444616 0.329727
+v -1.606042 -2.350899 0.325692
+v -1.839504 -2.257183 0.321657
+v -2.072965 -2.163467 0.317622
+v -2.306426 -2.069752 0.313587
+v -2.539887 -1.976036 0.309552
+v -2.773349 -1.882320 0.305517
+v -3.006810 -1.788605 0.301483
+v -3.240271 -1.694889 0.297448
+v -3.473733 -1.601173 0.293413
+v -3.707194 -1.507457 0.289378
+v -3.940656 -1.413742 0.285343
+v -4.174116 -1.320026 0.281308
+v 2.526423 -3.874441 0.388685
+v 2.292962 -3.780725 0.384650
+v 2.059500 -3.687009 0.380615
+v 1.826039 -3.593294 0.376580
+v 1.592578 -3.499577 0.372545
+v 1.359116 -3.405861 0.368510
+v 1.125655 -3.312146 0.364475
+v 0.892194 -3.218430 0.360440
+v 0.658732 -3.124714 0.356405
+v 0.425271 -3.030998 0.352371
+v 0.191809 -2.937282 0.348336
+v -0.041652 -2.843566 0.344300
+v -0.275113 -2.749850 0.340265
+v -0.508575 -2.656135 0.336230
+v -0.742036 -2.562419 0.332195
+v -0.975497 -2.468703 0.328160
+v -1.208959 -2.374988 0.324125
+v -1.442420 -2.281271 0.320090
+v -1.675881 -2.187556 0.316055
+v -1.909343 -2.093840 0.312021
+v -2.142804 -2.000124 0.307986
+v -2.376266 -1.906408 0.303951
+v -2.609727 -1.812692 0.299916
+v -2.843188 -1.718977 0.295881
+v -3.076649 -1.625261 0.291846
+v -3.310111 -1.531545 0.287811
+v -3.543572 -1.437829 0.283776
+v -3.777034 -1.344114 0.279741
+v -4.010494 -1.250398 0.275706
+v -4.243956 -1.156682 0.271671
+v 2.690045 -3.804814 0.383083
+v 2.456584 -3.711097 0.379048
+v 2.223123 -3.617381 0.375013
+v 1.989661 -3.523665 0.370978
+v 1.756200 -3.429949 0.366943
+v 1.522738 -3.336234 0.362908
+v 1.289277 -3.242518 0.358873
+v 1.055816 -3.148802 0.354838
+v 0.822354 -3.055086 0.350803
+v 0.588893 -2.961370 0.346768
+v 0.355431 -2.867654 0.342733
+v 0.121970 -2.773938 0.338698
+v -0.111491 -2.680223 0.334663
+v -0.344953 -2.586506 0.330628
+v -0.578414 -2.492791 0.326593
+v -0.811875 -2.399075 0.322558
+v -1.045337 -2.305359 0.318523
+v -1.278798 -2.211644 0.314488
+v -1.512259 -2.117928 0.310453
+v -1.745721 -2.024212 0.306418
+v -1.979182 -1.930496 0.302383
+v -2.212643 -1.836780 0.298348
+v -2.446105 -1.743064 0.294313
+v -2.679566 -1.649349 0.290278
+v -2.913028 -1.555633 0.286243
+v -3.146489 -1.461917 0.282208
+v -3.379950 -1.368201 0.278173
+v -3.613411 -1.274486 0.274138
+v -3.846873 -1.180770 0.270103
+v -4.080334 -1.087054 0.266068
+v -4.313795 -0.993338 0.262033
+v 2.853667 -3.735186 0.377481
+v 2.620206 -3.641469 0.373446
+v 2.386744 -3.547754 0.369411
+v 2.153283 -3.454038 0.365376
+v 1.919822 -3.360322 0.361341
+v 1.686360 -3.266606 0.357306
+v 1.452899 -3.172890 0.353271
+v 1.219437 -3.079174 0.349236
+v 0.985976 -2.985458 0.345201
+v 0.752515 -2.891742 0.341166
+v 0.519053 -2.798027 0.337131
+v 0.285592 -2.704310 0.333096
+v 0.052131 -2.610595 0.329061
+v -0.181331 -2.516879 0.325026
+v -0.414792 -2.423163 0.320991
+v -0.648253 -2.329447 0.316956
+v -0.881715 -2.235731 0.312921
+v -1.115176 -2.142015 0.308886
+v -1.348638 -2.048300 0.304851
+v -1.582099 -1.954584 0.300816
+v -1.815560 -1.860868 0.296781
+v -2.049021 -1.767152 0.292746
+v -2.282483 -1.673437 0.288711
+v -2.515944 -1.579721 0.284676
+v -2.749406 -1.486005 0.280641
+v -2.982867 -1.392290 0.276606
+v -3.216328 -1.298574 0.272572
+v -3.449790 -1.204858 0.268537
+v -3.683251 -1.111142 0.264502
+v -3.916712 -1.017426 0.260467
+v -4.150173 -0.923711 0.256432
+v -4.383635 -0.829995 0.252397
+v 3.017289 -3.665558 0.371879
+v 2.783828 -3.571841 0.367844
+v 2.550366 -3.478126 0.363809
+v 2.316905 -3.384410 0.359774
+v 2.083444 -3.290694 0.355739
+v 1.849982 -3.196978 0.351704
+v 1.616521 -3.103262 0.347669
+v 1.383060 -3.009546 0.343634
+v 1.149598 -2.915830 0.339599
+v 0.916137 -2.822114 0.335564
+v 0.682675 -2.728399 0.331529
+v 0.449214 -2.634683 0.327494
+v 0.215753 -2.540967 0.323459
+v -0.017709 -2.447251 0.319424
+v -0.251170 -2.353535 0.315389
+v -0.484631 -2.259820 0.311354
+v -0.718093 -2.166104 0.307319
+v -0.951554 -2.072388 0.303284
+v -1.185016 -1.978672 0.299249
+v -1.418477 -1.884956 0.295214
+v -1.651938 -1.791241 0.291179
+v -1.885400 -1.697525 0.287144
+v -2.118861 -1.603809 0.283109
+v -2.352322 -1.510093 0.279074
+v -2.585784 -1.416377 0.275039
+v -2.819245 -1.322662 0.271004
+v -3.052706 -1.228946 0.266969
+v -3.286168 -1.135230 0.262934
+v -3.519629 -1.041514 0.258899
+v -3.753090 -0.947798 0.254864
+v -3.986552 -0.854083 0.250829
+v -4.220013 -0.760367 0.246794
+v -4.453474 -0.666651 0.242759
+v 3.180911 -3.595930 0.366277
+v 2.947450 -3.502214 0.362242
+v 2.713988 -3.408498 0.358207
+v 2.480527 -3.314782 0.354172
+v 2.247066 -3.221066 0.350137
+v 2.013604 -3.127350 0.346102
+v 1.780143 -3.033635 0.342067
+v 1.546681 -2.939919 0.338032
+v 1.313220 -2.846202 0.333997
+v 1.079759 -2.752487 0.329962
+v 0.846297 -2.658771 0.325927
+v 0.612836 -2.565055 0.321892
+v 0.379375 -2.471339 0.317857
+v 0.145913 -2.377623 0.313822
+v -0.087548 -2.283908 0.309787
+v -0.321009 -2.190192 0.305752
+v -0.554471 -2.096476 0.301717
+v -0.787932 -2.002760 0.297682
+v -1.021394 -1.909044 0.293647
+v -1.254855 -1.815328 0.289612
+v -1.488316 -1.721613 0.285577
+v -1.721778 -1.627897 0.281542
+v -1.955239 -1.534181 0.277507
+v -2.188700 -1.440465 0.273472
+v -2.422162 -1.346750 0.269437
+v -2.655623 -1.253034 0.265402
+v -2.889084 -1.159318 0.261367
+v -3.122546 -1.065602 0.257332
+v -3.356007 -0.971886 0.253297
+v -3.589468 -0.878170 0.249262
+v -3.822929 -0.784455 0.245227
+v -4.056391 -0.690739 0.241192
+v -4.289852 -0.597024 0.237157
+v -4.523314 -0.503308 0.233122
+v 3.344533 -3.526303 0.360675
+v 3.111072 -3.432586 0.356640
+v 2.877610 -3.338870 0.352605
+v 2.644149 -3.245154 0.348570
+v 2.410687 -3.151438 0.344535
+v 2.177226 -3.057723 0.340500
+v 1.943765 -2.964007 0.336465
+v 1.710303 -2.870291 0.332430
+v 1.476842 -2.776575 0.328395
+v 1.243381 -2.682859 0.324360
+v 1.009919 -2.589143 0.320325
+v 0.776458 -2.495427 0.316290
+v 0.542997 -2.401711 0.312255
+v 0.309535 -2.307995 0.308220
+v 0.076074 -2.214280 0.304185
+v -0.157387 -2.120564 0.300150
+v -0.390849 -2.026848 0.296115
+v -0.624310 -1.933132 0.292080
+v -0.857772 -1.839417 0.288045
+v -1.091233 -1.745700 0.284010
+v -1.324694 -1.651985 0.279975
+v -1.558156 -1.558269 0.275940
+v -1.791617 -1.464553 0.271905
+v -2.025078 -1.370837 0.267870
+v -2.258540 -1.277122 0.263835
+v -2.492001 -1.183406 0.259800
+v -2.725462 -1.089690 0.255765
+v -2.958924 -0.995974 0.251730
+v -3.192385 -0.902259 0.247695
+v -3.425846 -0.808543 0.243660
+v -3.659307 -0.714827 0.239625
+v -3.892769 -0.621111 0.235590
+v -4.126230 -0.527396 0.231555
+v -4.359692 -0.433680 0.227520
+v -4.593153 -0.339964 0.223485
+v 3.508155 -3.456674 0.355073
+v 3.274693 -3.362958 0.351038
+v 3.041232 -3.269243 0.347003
+v 2.807771 -3.175527 0.342968
+v 2.574309 -3.081810 0.338933
+v 2.340848 -2.988095 0.334898
+v 2.107387 -2.894379 0.330863
+v 1.873925 -2.800663 0.326828
+v 1.640464 -2.706947 0.322793
+v 1.407002 -2.613231 0.318758
+v 1.173541 -2.519516 0.314723
+v 0.940080 -2.425799 0.310688
+v 0.706618 -2.332083 0.306653
+v 0.473157 -2.238368 0.302618
+v 0.239696 -2.144652 0.298583
+v 0.006234 -2.050936 0.294548
+v -0.227227 -1.957220 0.290513
+v -0.460688 -1.863505 0.286478
+v -0.694150 -1.769789 0.282443
+v -0.927611 -1.676073 0.278408
+v -1.161072 -1.582357 0.274373
+v -1.394534 -1.488641 0.270338
+v -1.627995 -1.394925 0.266303
+v -1.861456 -1.301210 0.262268
+v -2.094918 -1.207494 0.258233
+v -2.328379 -1.113778 0.254198
+v -2.561840 -1.020062 0.250163
+v -2.795302 -0.926347 0.246128
+v -3.028763 -0.832631 0.242093
+v -3.262224 -0.738915 0.238058
+v -3.495686 -0.645199 0.234023
+v -3.729147 -0.551483 0.229988
+v -3.962608 -0.457768 0.225953
+v -4.196070 -0.364052 0.221918
+v -4.429531 -0.270336 0.217883
+v -4.662992 -0.176620 0.213848
+v 3.671777 -3.387047 0.349471
+v 3.438316 -3.293330 0.345436
+v 3.204854 -3.199615 0.341401
+v 2.971393 -3.105899 0.337366
+v 2.737931 -3.012183 0.333331
+v 2.504470 -2.918467 0.329296
+v 2.271009 -2.824751 0.325261
+v 2.037547 -2.731035 0.321226
+v 1.804086 -2.637319 0.317191
+v 1.570624 -2.543603 0.313156
+v 1.337163 -2.449888 0.309121
+v 1.103702 -2.356172 0.305086
+v 0.870240 -2.262455 0.301051
+v 0.636779 -2.168740 0.297016
+v 0.403318 -2.075024 0.292981
+v 0.169856 -1.981308 0.288946
+v -0.063605 -1.887592 0.284911
+v -0.297066 -1.793877 0.280876
+v -0.530528 -1.700161 0.276841
+v -0.763989 -1.606445 0.272806
+v -0.997450 -1.512729 0.268771
+v -1.230912 -1.419013 0.264736
+v -1.464373 -1.325298 0.260701
+v -1.697834 -1.231582 0.256666
+v -1.931295 -1.137866 0.252631
+v -2.164757 -1.044150 0.248596
+v -2.398218 -0.950434 0.244561
+v -2.631680 -0.856719 0.240526
+v -2.865141 -0.763003 0.236491
+v -3.098603 -0.669287 0.232456
+v -3.332064 -0.575571 0.228421
+v -3.565525 -0.481856 0.224386
+v -3.798986 -0.388140 0.220351
+v -4.032447 -0.294424 0.216316
+v -4.265909 -0.200708 0.212281
+v -4.499370 -0.106993 0.208246
+v -4.732831 -0.013277 0.204211
+v 3.835399 -3.317418 0.343869
+v 3.601938 -3.223703 0.339834
+v 3.368476 -3.129987 0.335799
+v 3.135015 -3.036271 0.331764
+v 2.901554 -2.942555 0.327729
+v 2.668092 -2.848839 0.323694
+v 2.434631 -2.755123 0.319659
+v 2.201169 -2.661407 0.315624
+v 1.967708 -2.567691 0.311589
+v 1.734246 -2.473976 0.307554
+v 1.500785 -2.380260 0.303519
+v 1.267324 -2.286544 0.299484
+v 1.033862 -2.192828 0.295449
+v 0.800401 -2.099112 0.291414
+v 0.566940 -2.005396 0.287379
+v 0.333478 -1.911680 0.283344
+v 0.100017 -1.817965 0.279309
+v -0.133444 -1.724249 0.275274
+v -0.366906 -1.630533 0.271239
+v -0.600367 -1.536817 0.267204
+v -0.833828 -1.443102 0.263169
+v -1.067290 -1.349386 0.259134
+v -1.300751 -1.255670 0.255099
+v -1.534212 -1.161954 0.251064
+v -1.767674 -1.068238 0.247029
+v -2.001135 -0.974522 0.242994
+v -2.234596 -0.880807 0.238959
+v -2.468058 -0.787091 0.234924
+v -2.701519 -0.693375 0.230889
+v -2.934980 -0.599659 0.226854
+v -3.168442 -0.505944 0.222819
+v -3.401903 -0.412228 0.218784
+v -3.635364 -0.318512 0.214749
+v -3.868825 -0.224796 0.210714
+v -4.102286 -0.131081 0.206679
+v -4.335748 -0.037365 0.202644
+v -4.569209 0.056351 0.198609
+v -4.802670 0.150067 0.194574
+v 3.999021 -3.247791 0.338267
+v 3.765560 -3.154075 0.334232
+v 3.532098 -3.060359 0.330197
+v 3.298637 -2.966643 0.326162
+v 3.065176 -2.872927 0.322127
+v 2.831714 -2.779212 0.318092
+v 2.598253 -2.685495 0.314057
+v 2.364791 -2.591780 0.310022
+v 2.131330 -2.498064 0.305987
+v 1.897868 -2.404348 0.301952
+v 1.664407 -2.310632 0.297917
+v 1.430946 -2.216916 0.293882
+v 1.197484 -2.123200 0.289847
+v 0.964023 -2.029484 0.285812
+v 0.730562 -1.935768 0.281777
+v 0.497100 -1.842052 0.277742
+v 0.263639 -1.748337 0.273707
+v 0.030178 -1.654621 0.269672
+v -0.203284 -1.560905 0.265637
+v -0.436745 -1.467189 0.261602
+v -0.670206 -1.373474 0.257567
+v -0.903668 -1.279758 0.253532
+v -1.137129 -1.186042 0.249497
+v -1.370590 -1.092326 0.245462
+v -1.604052 -0.998610 0.241427
+v -1.837513 -0.904895 0.237392
+v -2.070974 -0.811179 0.233357
+v -2.304435 -0.717463 0.229322
+v -2.537897 -0.623747 0.225287
+v -2.771358 -0.530031 0.221252
+v -3.004820 -0.436316 0.217217
+v -3.238281 -0.342600 0.213182
+v -3.471742 -0.248884 0.209147
+v -3.705204 -0.155168 0.205112
+v -3.938665 -0.061453 0.201077
+v -4.172126 0.032263 0.197042
+v -4.405587 0.125979 0.193007
+v -4.639049 0.219695 0.188972
+v -4.872510 0.313411 0.184937
+v 4.162643 -3.178163 0.332665
+v 3.929182 -3.084447 0.328630
+v 3.695721 -2.990731 0.324595
+v 3.462259 -2.897015 0.320560
+v 3.228797 -2.803299 0.316525
+v 2.995336 -2.709584 0.312490
+v 2.761875 -2.615868 0.308455
+v 2.528413 -2.522151 0.304420
+v 2.294952 -2.428436 0.300385
+v 2.061491 -2.334720 0.296350
+v 1.828029 -2.241004 0.292315
+v 1.594568 -2.147288 0.288280
+v 1.361106 -2.053572 0.284245
+v 1.127645 -1.959856 0.280210
+v 0.894184 -1.866141 0.276175
+v 0.660722 -1.772425 0.272140
+v 0.427261 -1.678709 0.268105
+v 0.193800 -1.584993 0.264070
+v -0.039662 -1.491277 0.260035
+v -0.273123 -1.397561 0.256000
+v -0.506584 -1.303846 0.251965
+v -0.740046 -1.210130 0.247930
+v -0.973507 -1.116414 0.243895
+v -1.206968 -1.022698 0.239860
+v -1.440430 -0.928983 0.235825
+v -1.673891 -0.835267 0.231790
+v -1.907352 -0.741551 0.227755
+v -2.140813 -0.647835 0.223720
+v -2.374275 -0.554119 0.219685
+v -2.607736 -0.460404 0.215650
+v -2.841197 -0.366688 0.211615
+v -3.074659 -0.272972 0.207580
+v -3.308120 -0.179256 0.203545
+v -3.541582 -0.085541 0.199510
+v -3.775043 0.008175 0.195475
+v -4.008504 0.101891 0.191440
+v -4.241965 0.195607 0.187405
+v -4.475427 0.289323 0.183370
+v -4.708888 0.383039 0.179335
+v -4.942349 0.476755 0.175300
+v 4.326265 -3.108535 0.327063
+v 4.092804 -3.014819 0.323028
+v 3.859343 -2.921103 0.318993
+v 3.625881 -2.827387 0.314958
+v 3.392420 -2.733672 0.310923
+v 3.158958 -2.639956 0.306888
+v 2.925497 -2.546240 0.302853
+v 2.692035 -2.452524 0.298818
+v 2.458574 -2.358808 0.294783
+v 2.225112 -2.265092 0.290748
+v 1.991651 -2.171377 0.286713
+v 1.758190 -2.077660 0.282678
+v 1.524728 -1.983944 0.278643
+v 1.291267 -1.890228 0.274608
+v 1.057806 -1.796513 0.270573
+v 0.824344 -1.702797 0.266538
+v 0.590883 -1.609081 0.262503
+v 0.357422 -1.515365 0.258468
+v 0.123960 -1.421649 0.254433
+v -0.109501 -1.327934 0.250398
+v -0.342962 -1.234218 0.246363
+v -0.576424 -1.140502 0.242328
+v -0.809885 -1.046786 0.238293
+v -1.043346 -0.953071 0.234258
+v -1.276808 -0.859355 0.230223
+v -1.510269 -0.765639 0.226188
+v -1.743730 -0.671923 0.222153
+v -1.977192 -0.578207 0.218118
+v -2.210653 -0.484491 0.214083
+v -2.444114 -0.390776 0.210048
+v -2.677576 -0.297060 0.206013
+v -2.911037 -0.203344 0.201978
+v -3.144498 -0.109628 0.197943
+v -3.377960 -0.015913 0.193908
+v -3.611421 0.077803 0.189873
+v -3.844882 0.171519 0.185838
+v -4.078343 0.265235 0.181803
+v -4.311805 0.358951 0.177768
+v -4.545266 0.452667 0.173733
+v -4.778728 0.546382 0.169698
+v -5.012189 0.640098 0.165663
+v 4.489887 -3.038907 0.321461
+v 4.256426 -2.945192 0.317426
+v 4.022964 -2.851475 0.313390
+v 3.789503 -2.757760 0.309355
+v 3.556042 -2.664043 0.305321
+v 3.322580 -2.570328 0.301286
+v 3.089119 -2.476612 0.297251
+v 2.855658 -2.382896 0.293216
+v 2.622196 -2.289180 0.289181
+v 2.388735 -2.195465 0.285146
+v 2.155273 -2.101748 0.281111
+v 1.921812 -2.008032 0.277076
+v 1.688350 -1.914317 0.273041
+v 1.454889 -1.820600 0.269006
+v 1.221428 -1.726885 0.264971
+v 0.987966 -1.633169 0.260936
+v 0.754505 -1.539453 0.256901
+v 0.521044 -1.445737 0.252866
+v 0.287582 -1.352022 0.248831
+v 0.054121 -1.258306 0.244796
+v -0.179340 -1.164590 0.240761
+v -0.412802 -1.070874 0.236726
+v -0.646263 -0.977158 0.232691
+v -0.879724 -0.883443 0.228656
+v -1.113186 -0.789727 0.224621
+v -1.346647 -0.696011 0.220586
+v -1.580108 -0.602295 0.216551
+v -1.813570 -0.508579 0.212516
+v -2.047031 -0.414864 0.208481
+v -2.280492 -0.321148 0.204446
+v -2.513954 -0.227432 0.200411
+v -2.747415 -0.133716 0.196376
+v -2.980876 -0.040001 0.192341
+v -3.214338 0.053715 0.188306
+v -3.447799 0.147431 0.184271
+v -3.681260 0.241147 0.180236
+v -3.914722 0.334863 0.176201
+v -4.148183 0.428579 0.172166
+v -4.381644 0.522295 0.168131
+v -4.615106 0.616011 0.164096
+v -4.848567 0.709726 0.160061
+v -5.082028 0.803442 0.156026
+v 4.653510 -2.969280 0.315859
+v 4.420048 -2.875564 0.311824
+v 4.186587 -2.781847 0.307789
+v 3.953125 -2.688132 0.303754
+v 3.719664 -2.594416 0.299719
+v 3.486202 -2.500700 0.295684
+v 3.252741 -2.406984 0.291649
+v 3.019279 -2.313268 0.287614
+v 2.785818 -2.219553 0.283579
+v 2.552357 -2.125836 0.279544
+v 2.318895 -2.032120 0.275509
+v 2.085434 -1.938404 0.271474
+v 1.851972 -1.844689 0.267439
+v 1.618511 -1.750973 0.263404
+v 1.385050 -1.657257 0.259369
+v 1.151588 -1.563541 0.255334
+v 0.918127 -1.469826 0.251299
+v 0.684666 -1.376110 0.247264
+v 0.451204 -1.282394 0.243229
+v 0.217743 -1.188678 0.239194
+v -0.015718 -1.094962 0.235159
+v -0.249180 -1.001246 0.231124
+v -0.482641 -0.907531 0.227089
+v -0.716102 -0.813815 0.223054
+v -0.949564 -0.720099 0.219019
+v -1.183025 -0.626383 0.214984
+v -1.416486 -0.532667 0.210949
+v -1.649948 -0.438952 0.206914
+v -1.883409 -0.345236 0.202879
+v -2.116870 -0.251520 0.198844
+v -2.350331 -0.157804 0.194809
+v -2.583793 -0.064088 0.190774
+v -2.817254 0.029627 0.186739
+v -3.050715 0.123343 0.182704
+v -3.284177 0.217059 0.178669
+v -3.517638 0.310775 0.174634
+v -3.751100 0.404491 0.170599
+v -3.984561 0.498207 0.166564
+v -4.218022 0.591923 0.162529
+v -4.451484 0.685638 0.158494
+v -4.684945 0.779354 0.154459
+v -4.918406 0.873070 0.150424
+v -5.151868 0.966786 0.146389
+v 4.817132 -2.899652 0.310257
+v 4.583670 -2.805936 0.306221
+v 4.350208 -2.712219 0.302186
+v 4.116747 -2.618504 0.298151
+v 3.883286 -2.524788 0.294116
+v 3.649824 -2.431072 0.290082
+v 3.416363 -2.337356 0.286047
+v 3.182901 -2.243640 0.282012
+v 2.949440 -2.149925 0.277977
+v 2.715979 -2.056208 0.273942
+v 2.482517 -1.962493 0.269907
+v 2.249056 -1.868777 0.265872
+v 2.015594 -1.775061 0.261837
+v 1.782133 -1.681345 0.257802
+v 1.548671 -1.587629 0.253767
+v 1.315210 -1.493914 0.249732
+v 1.081749 -1.400198 0.245697
+v 0.848288 -1.306482 0.241662
+v 0.614826 -1.212766 0.237627
+v 0.381365 -1.119050 0.233592
+v 0.147904 -1.025334 0.229557
+v -0.085558 -0.931619 0.225522
+v -0.319019 -0.837903 0.221487
+v -0.552480 -0.744187 0.217452
+v -0.785942 -0.650471 0.213417
+v -1.019403 -0.556755 0.209382
+v -1.252864 -0.463039 0.205347
+v -1.486326 -0.369324 0.201312
+v -1.719787 -0.275608 0.197277
+v -1.953248 -0.181892 0.193242
+v -2.186710 -0.088176 0.189207
+v -2.420171 0.005539 0.185172
+v -2.653632 0.099255 0.181137
+v -2.887094 0.192971 0.177102
+v -3.120555 0.286687 0.173067
+v -3.354016 0.380403 0.169032
+v -3.587478 0.474118 0.164997
+v -3.820939 0.567834 0.160962
+v -4.054400 0.661550 0.156927
+v -4.287862 0.755266 0.152892
+v -4.521323 0.848982 0.148857
+v -4.754785 0.942698 0.144822
+v -4.988246 1.036414 0.140787
+v -5.221706 1.130129 0.136752
+v 4.980753 -2.830024 0.304654
+v 4.747292 -2.736308 0.300619
+v 4.513830 -2.642592 0.296584
+v 4.280369 -2.548876 0.292549
+v 4.046907 -2.455160 0.288514
+v 3.813446 -2.361444 0.284479
+v 3.579985 -2.267728 0.280444
+v 3.346523 -2.174013 0.276409
+v 3.113062 -2.080297 0.272375
+v 2.879601 -1.986581 0.268340
+v 2.646139 -1.892865 0.264305
+v 2.412678 -1.799149 0.260270
+v 2.179216 -1.705433 0.256235
+v 1.945755 -1.611717 0.252200
+v 1.712294 -1.518002 0.248165
+v 1.478832 -1.424286 0.244130
+v 1.245371 -1.330570 0.240095
+v 1.011909 -1.236854 0.236060
+v 0.778448 -1.143138 0.232025
+v 0.544987 -1.049423 0.227990
+v 0.311526 -0.955707 0.223955
+v 0.078064 -0.861991 0.219920
+v -0.155397 -0.768275 0.215885
+v -0.388859 -0.674559 0.211850
+v -0.622320 -0.580843 0.207815
+v -0.855781 -0.487128 0.203780
+v -1.089242 -0.393412 0.199745
+v -1.322704 -0.299696 0.195710
+v -1.556165 -0.205980 0.191675
+v -1.789626 -0.112264 0.187640
+v -2.023088 -0.018548 0.183605
+v -2.256549 0.075167 0.179570
+v -2.490010 0.168883 0.175535
+v -2.723472 0.262599 0.171500
+v -2.956933 0.356315 0.167465
+v -3.190394 0.450030 0.163430
+v -3.423856 0.543746 0.159395
+v -3.657317 0.637462 0.155360
+v -3.890779 0.731178 0.151325
+v -4.124240 0.824894 0.147290
+v -4.357701 0.918610 0.143255
+v -4.591162 1.012325 0.139220
+v -4.824624 1.106042 0.135185
+v -5.058085 1.199757 0.131150
+v -5.291546 1.293473 0.127115
+v 5.144376 -2.760396 0.299052
+v 4.910913 -2.666680 0.295017
+v 4.677453 -2.572964 0.290982
+v 4.443991 -2.479249 0.286947
+v 4.210530 -2.385532 0.282912
+v 3.977068 -2.291817 0.278877
+v 3.743607 -2.198101 0.274843
+v 3.510145 -2.104385 0.270808
+v 3.276684 -2.010669 0.266773
+v 3.043222 -1.916953 0.262738
+v 2.809761 -1.823237 0.258703
+v 2.576299 -1.729521 0.254668
+v 2.342838 -1.635805 0.250633
+v 2.109377 -1.542089 0.246598
+v 1.875915 -1.448374 0.242563
+v 1.642454 -1.354658 0.238528
+v 1.408993 -1.260942 0.234493
+v 1.175532 -1.167226 0.230458
+v 0.942070 -1.073511 0.226423
+v 0.708609 -0.979795 0.222388
+v 0.475148 -0.886079 0.218353
+v 0.241686 -0.792363 0.214318
+v 0.008225 -0.698647 0.210283
+v -0.225236 -0.604931 0.206248
+v -0.458698 -0.511216 0.202213
+v -0.692159 -0.417500 0.198178
+v -0.925620 -0.323784 0.194143
+v -1.159082 -0.230068 0.190108
+v -1.392543 -0.136352 0.186073
+v -1.626004 -0.042636 0.182038
+v -1.859466 0.051079 0.178003
+v -2.092927 0.144795 0.173968
+v -2.326388 0.238511 0.169933
+v -2.559850 0.332227 0.165898
+v -2.793311 0.425943 0.161863
+v -3.026772 0.519658 0.157828
+v -3.260234 0.613374 0.153793
+v -3.493695 0.707090 0.149758
+v -3.727157 0.800806 0.145723
+v -3.960618 0.894522 0.141688
+v -4.194079 0.988238 0.137653
+v -4.427540 1.081954 0.133618
+v -4.661001 1.175669 0.129583
+v -4.894464 1.269385 0.125548
+v -5.127924 1.363101 0.121513
+v -5.361385 1.456817 0.117478
+v 5.307998 -2.690768 0.293450
+v 5.074536 -2.597052 0.289415
+v 4.841075 -2.503336 0.285380
+v 4.607614 -2.409621 0.281345
+v 4.374152 -2.315905 0.277310
+v 4.140691 -2.222188 0.273275
+v 3.907229 -2.128473 0.269240
+v 3.673767 -2.034757 0.265205
+v 3.440306 -1.941041 0.261170
+v 3.206845 -1.847325 0.257135
+v 2.973383 -1.753609 0.253100
+v 2.739922 -1.659893 0.249065
+v 2.506460 -1.566177 0.245030
+v 2.272999 -1.472462 0.240995
+v 2.039538 -1.378746 0.236960
+v 1.806076 -1.285030 0.232925
+v 1.572615 -1.191314 0.228890
+v 1.339153 -1.097599 0.224855
+v 1.105692 -1.003883 0.220821
+v 0.872231 -0.910167 0.216786
+v 0.638770 -0.816451 0.212751
+v 0.405308 -0.722735 0.208716
+v 0.171847 -0.629019 0.204681
+v -0.061614 -0.535303 0.200646
+v -0.295076 -0.441588 0.196611
+v -0.528537 -0.347872 0.192576
+v -0.761998 -0.254156 0.188541
+v -0.995460 -0.160440 0.184506
+v -1.228921 -0.066724 0.180471
+v -1.462382 0.026991 0.176436
+v -1.695844 0.120707 0.172401
+v -1.929305 0.214423 0.168366
+v -2.162766 0.308139 0.164331
+v -2.396228 0.401855 0.160296
+v -2.629689 0.495571 0.156261
+v -2.863150 0.589286 0.152226
+v -3.096612 0.683002 0.148191
+v -3.330073 0.776718 0.144156
+v -3.563535 0.870434 0.140121
+v -3.796996 0.964150 0.136086
+v -4.030457 1.057866 0.132051
+v -4.263918 1.151582 0.128016
+v -4.497379 1.245297 0.123981
+v -4.730841 1.339013 0.119946
+v -4.964303 1.432729 0.115911
+v -5.197763 1.526445 0.111876
+v -5.431225 1.620160 0.107841
+v 5.471620 -2.621141 0.287848
+v 5.238158 -2.527424 0.283813
+v 5.004697 -2.433708 0.279778
+v 4.771235 -2.339993 0.275743
+v 4.537774 -2.246277 0.271708
+v 4.304313 -2.152560 0.267673
+v 4.070851 -2.058845 0.263638
+v 3.837389 -1.965129 0.259603
+v 3.603928 -1.871413 0.255568
+v 3.370467 -1.777697 0.251533
+v 3.137005 -1.683981 0.247498
+v 2.903544 -1.590265 0.243463
+v 2.670082 -1.496549 0.239429
+v 2.436621 -1.402834 0.235394
+v 2.203160 -1.309118 0.231359
+v 1.969698 -1.215402 0.227324
+v 1.736237 -1.121686 0.223289
+v 1.502776 -1.027971 0.219254
+v 1.269314 -0.934255 0.215219
+v 1.035853 -0.840539 0.211184
+v 0.802391 -0.746823 0.207149
+v 0.568930 -0.653107 0.203114
+v 0.335469 -0.559391 0.199079
+v 0.102008 -0.465676 0.195044
+v -0.131454 -0.371960 0.191009
+v -0.364915 -0.278244 0.186974
+v -0.598377 -0.184528 0.182939
+v -0.831838 -0.090812 0.178904
+v -1.065299 0.002903 0.174869
+v -1.298761 0.096619 0.170834
+v -1.532222 0.190335 0.166799
+v -1.765683 0.284051 0.162764
+v -1.999144 0.377767 0.158729
+v -2.232605 0.471483 0.154694
+v -2.466067 0.565198 0.150659
+v -2.699528 0.658914 0.146624
+v -2.932990 0.752630 0.142589
+v -3.166451 0.846346 0.138554
+v -3.399912 0.940062 0.134519
+v -3.633374 1.033778 0.130484
+v -3.866836 1.127494 0.126449
+v -4.100297 1.221209 0.122414
+v -4.333757 1.314925 0.118379
+v -4.567219 1.408641 0.114344
+v -4.800680 1.502357 0.110309
+v -5.034142 1.596073 0.106274
+v -5.267603 1.689788 0.102239
+v -5.501064 1.783504 0.098204
+v 5.635241 -2.551513 0.282246
+v 5.401779 -2.457797 0.278211
+v 5.168319 -2.364081 0.274176
+v 4.934856 -2.270365 0.270141
+v 4.701396 -2.176649 0.266106
+v 4.467934 -2.082933 0.262071
+v 4.234472 -1.989217 0.258036
+v 4.001011 -1.895501 0.254001
+v 3.767550 -1.801785 0.249966
+v 3.534088 -1.708070 0.245931
+v 3.300627 -1.614354 0.241896
+v 3.067165 -1.520638 0.237861
+v 2.833704 -1.426922 0.233826
+v 2.600243 -1.333206 0.229791
+v 2.366781 -1.239491 0.225756
+v 2.133320 -1.145774 0.221721
+v 1.899859 -1.052059 0.217686
+v 1.666397 -0.958343 0.213651
+v 1.432936 -0.864627 0.209616
+v 1.199475 -0.770911 0.205581
+v 0.966013 -0.677196 0.201546
+v 0.732552 -0.583480 0.197511
+v 0.499091 -0.489764 0.193476
+v 0.265629 -0.396048 0.189441
+v 0.032168 -0.302332 0.185406
+v -0.201293 -0.208616 0.181371
+v -0.434755 -0.114901 0.177336
+v -0.668216 -0.021185 0.173302
+v -0.901677 0.072531 0.169267
+v -1.135139 0.166247 0.165232
+v -1.368600 0.259963 0.161197
+v -1.602061 0.353679 0.157162
+v -1.835523 0.447395 0.153127
+v -2.068984 0.541110 0.149092
+v -2.302445 0.634826 0.145057
+v -2.535906 0.728542 0.141022
+v -2.769368 0.822258 0.136987
+v -3.002829 0.915974 0.132952
+v -3.236290 1.009689 0.128917
+v -3.469752 1.103406 0.124882
+v -3.703213 1.197121 0.120847
+v -3.936675 1.290837 0.116812
+v -4.170135 1.384553 0.112777
+v -4.403597 1.478269 0.108742
+v -4.637058 1.571984 0.104707
+v -4.870520 1.665701 0.100672
+v -5.103981 1.759416 0.096637
+v -5.337442 1.853132 0.092602
+v -5.570904 1.946848 0.088567
+vn 0.0077 0.0622 0.9980
+usemtl None
+s off
+f 2//1 254//1 104//1
+f 2//1 105//1 254//1
+f 205//1 204//1 3//1
+f 206//1 255//1 205//1
+f 207//1 256//1 206//1
+f 208//1 258//1 207//1
+f 209//1 261//1 208//1
+f 210//1 265//1 209//1
+f 211//1 270//1 210//1
+f 212//1 276//1 211//1
+f 213//1 283//1 212//1
+f 214//1 291//1 213//1
+f 215//1 300//1 214//1
+f 216//1 310//1 215//1
+f 217//1 321//1 216//1
+f 218//1 333//1 217//1
+f 219//1 346//1 218//1
+f 220//1 360//1 219//1
+f 221//1 375//1 220//1
+f 222//1 391//1 221//1
+f 223//1 408//1 222//1
+f 224//1 426//1 223//1
+f 225//1 445//1 224//1
+f 226//1 465//1 225//1
+f 227//1 486//1 226//1
+f 228//1 508//1 227//1
+f 229//1 531//1 228//1
+f 230//1 555//1 229//1
+f 231//1 580//1 230//1
+f 232//1 606//1 231//1
+f 233//1 633//1 232//1
+f 234//1 661//1 233//1
+f 235//1 690//1 234//1
+f 236//1 720//1 235//1
+f 237//1 751//1 236//1
+f 238//1 783//1 237//1
+f 239//1 816//1 238//1
+f 240//1 850//1 239//1
+f 241//1 885//1 240//1
+f 242//1 921//1 241//1
+f 243//1 958//1 242//1
+f 244//1 996//1 243//1
+f 245//1 1035//1 244//1
+f 246//1 1075//1 245//1
+f 247//1 1116//1 246//1
+f 248//1 1158//1 247//1
+f 249//1 1201//1 248//1
+f 250//1 1245//1 249//1
+f 251//1 1290//1 250//1
+f 252//1 1336//1 251//1
+f 253//1 1383//1 252//1
+f 254//1 1431//1 253//1
+f 205//1 255//1 204//1
+f 255//1 203//1 204//1
+f 206//1 256//1 255//1
+f 256//1 257//1 255//1
+f 255//1 257//1 203//1
+f 257//1 202//1 203//1
+f 207//1 258//1 256//1
+f 258//1 259//1 256//1
+f 256//1 259//1 257//1
+f 259//1 260//1 257//1
+f 257//1 260//1 202//1
+f 260//1 201//1 202//1
+f 208//1 261//1 258//1
+f 261//1 262//1 258//1
+f 258//1 262//1 259//1
+f 262//1 263//1 259//1
+f 259//1 263//1 260//1
+f 263//1 264//1 260//1
+f 260//1 264//1 201//1
+f 264//1 200//1 201//1
+f 209//1 265//1 261//1
+f 265//1 266//1 261//1
+f 261//1 266//1 262//1
+f 266//1 267//1 262//1
+f 262//1 267//1 263//1
+f 267//1 268//1 263//1
+f 263//1 268//1 264//1
+f 268//1 269//1 264//1
+f 264//1 269//1 200//1
+f 269//1 199//1 200//1
+f 210//1 270//1 265//1
+f 270//1 271//1 265//1
+f 265//1 271//1 266//1
+f 271//1 272//1 266//1
+f 266//1 272//1 267//1
+f 272//1 273//1 267//1
+f 267//1 273//1 268//1
+f 273//1 274//1 268//1
+f 268//1 274//1 269//1
+f 274//1 275//1 269//1
+f 269//1 275//1 199//1
+f 275//1 198//1 199//1
+f 211//1 276//1 270//1
+f 276//1 277//1 270//1
+f 270//1 277//1 271//1
+f 277//1 278//1 271//1
+f 271//1 278//1 272//1
+f 278//1 279//1 272//1
+f 272//1 279//1 273//1
+f 279//1 280//1 273//1
+f 273//1 280//1 274//1
+f 280//1 281//1 274//1
+f 274//1 281//1 275//1
+f 281//1 282//1 275//1
+f 275//1 282//1 198//1
+f 282//1 197//1 198//1
+f 212//1 283//1 276//1
+f 283//1 284//1 276//1
+f 276//1 284//1 277//1
+f 284//1 285//1 277//1
+f 277//1 285//1 278//1
+f 285//1 286//1 278//1
+f 278//1 286//1 279//1
+f 286//1 287//1 279//1
+f 279//1 287//1 280//1
+f 287//1 288//1 280//1
+f 280//1 288//1 281//1
+f 288//1 289//1 281//1
+f 281//1 289//1 282//1
+f 289//1 290//1 282//1
+f 282//1 290//1 197//1
+f 290//1 196//1 197//1
+f 213//1 291//1 283//1
+f 291//1 292//1 283//1
+f 283//1 292//1 284//1
+f 292//1 293//1 284//1
+f 284//1 293//1 285//1
+f 293//1 294//1 285//1
+f 285//1 294//1 286//1
+f 294//1 295//1 286//1
+f 286//1 295//1 287//1
+f 295//1 296//1 287//1
+f 287//1 296//1 288//1
+f 296//1 297//1 288//1
+f 288//1 297//1 289//1
+f 297//1 298//1 289//1
+f 289//1 298//1 290//1
+f 298//1 299//1 290//1
+f 290//1 299//1 196//1
+f 299//1 195//1 196//1
+f 214//1 300//1 291//1
+f 300//1 301//1 291//1
+f 291//1 301//1 292//1
+f 301//1 302//1 292//1
+f 292//1 302//1 293//1
+f 302//1 303//1 293//1
+f 293//1 303//1 294//1
+f 303//1 304//1 294//1
+f 294//1 304//1 295//1
+f 304//1 305//1 295//1
+f 295//1 305//1 296//1
+f 305//1 306//1 296//1
+f 296//1 306//1 297//1
+f 306//1 307//1 297//1
+f 297//1 307//1 298//1
+f 307//1 308//1 298//1
+f 298//1 308//1 299//1
+f 308//1 309//1 299//1
+f 299//1 309//1 195//1
+f 309//1 194//1 195//1
+f 215//1 310//1 300//1
+f 310//1 311//1 300//1
+f 300//1 311//1 301//1
+f 311//1 312//1 301//1
+f 301//1 312//1 302//1
+f 312//1 313//1 302//1
+f 302//1 313//1 303//1
+f 313//1 314//1 303//1
+f 303//1 314//1 304//1
+f 314//1 315//1 304//1
+f 304//1 315//1 305//1
+f 315//1 316//1 305//1
+f 305//1 316//1 306//1
+f 316//1 317//1 306//1
+f 306//1 317//1 307//1
+f 317//1 318//1 307//1
+f 307//1 318//1 308//1
+f 318//1 319//1 308//1
+f 308//1 319//1 309//1
+f 319//1 320//1 309//1
+f 309//1 320//1 194//1
+f 320//1 193//1 194//1
+f 216//1 321//1 310//1
+f 321//1 322//1 310//1
+f 310//1 322//1 311//1
+f 322//1 323//1 311//1
+f 311//1 323//1 312//1
+f 323//1 324//1 312//1
+f 312//1 324//1 313//1
+f 324//1 325//1 313//1
+f 313//1 325//1 314//1
+f 325//1 326//1 314//1
+f 314//1 326//1 315//1
+f 326//1 327//1 315//1
+f 315//1 327//1 316//1
+f 327//1 328//1 316//1
+f 316//1 328//1 317//1
+f 328//1 329//1 317//1
+f 317//1 329//1 318//1
+f 329//1 330//1 318//1
+f 318//1 330//1 319//1
+f 330//1 331//1 319//1
+f 319//1 331//1 320//1
+f 331//1 332//1 320//1
+f 320//1 332//1 193//1
+f 332//1 192//1 193//1
+f 217//1 333//1 321//1
+f 333//1 334//1 321//1
+f 321//1 334//1 322//1
+f 334//1 335//1 322//1
+f 322//1 335//1 323//1
+f 335//1 336//1 323//1
+f 323//1 336//1 324//1
+f 336//1 337//1 324//1
+f 324//1 337//1 325//1
+f 337//1 338//1 325//1
+f 325//1 338//1 326//1
+f 338//1 339//1 326//1
+f 326//1 339//1 327//1
+f 339//1 340//1 327//1
+f 327//1 340//1 328//1
+f 340//1 341//1 328//1
+f 328//1 341//1 329//1
+f 341//1 342//1 329//1
+f 329//1 342//1 330//1
+f 342//1 343//1 330//1
+f 330//1 343//1 331//1
+f 343//1 344//1 331//1
+f 331//1 344//1 332//1
+f 344//1 345//1 332//1
+f 332//1 345//1 192//1
+f 345//1 191//1 192//1
+f 218//1 346//1 333//1
+f 346//1 347//1 333//1
+f 333//1 347//1 334//1
+f 347//1 348//1 334//1
+f 334//1 348//1 335//1
+f 348//1 349//1 335//1
+f 335//1 349//1 336//1
+f 349//1 350//1 336//1
+f 336//1 350//1 337//1
+f 350//1 351//1 337//1
+f 337//1 351//1 338//1
+f 351//1 352//1 338//1
+f 338//1 352//1 339//1
+f 352//1 353//1 339//1
+f 339//1 353//1 340//1
+f 353//1 354//1 340//1
+f 340//1 354//1 341//1
+f 354//1 355//1 341//1
+f 341//1 355//1 342//1
+f 355//1 356//1 342//1
+f 342//1 356//1 343//1
+f 356//1 357//1 343//1
+f 343//1 357//1 344//1
+f 357//1 358//1 344//1
+f 344//1 358//1 345//1
+f 358//1 359//1 345//1
+f 345//1 359//1 191//1
+f 359//1 190//1 191//1
+f 219//1 360//1 346//1
+f 360//1 361//1 346//1
+f 346//1 361//1 347//1
+f 361//1 362//1 347//1
+f 347//1 362//1 348//1
+f 362//1 363//1 348//1
+f 348//1 363//1 349//1
+f 363//1 364//1 349//1
+f 349//1 364//1 350//1
+f 364//1 365//1 350//1
+f 350//1 365//1 351//1
+f 365//1 366//1 351//1
+f 351//1 366//1 352//1
+f 366//1 367//1 352//1
+f 352//1 367//1 353//1
+f 367//1 368//1 353//1
+f 353//1 368//1 354//1
+f 368//1 369//1 354//1
+f 354//1 369//1 355//1
+f 369//1 370//1 355//1
+f 355//1 370//1 356//1
+f 370//1 371//1 356//1
+f 356//1 371//1 357//1
+f 371//1 372//1 357//1
+f 357//1 372//1 358//1
+f 372//1 373//1 358//1
+f 358//1 373//1 359//1
+f 373//1 374//1 359//1
+f 359//1 374//1 190//1
+f 374//1 189//1 190//1
+f 220//1 375//1 360//1
+f 375//1 376//1 360//1
+f 360//1 376//1 361//1
+f 376//1 377//1 361//1
+f 361//1 377//1 362//1
+f 377//1 378//1 362//1
+f 362//1 378//1 363//1
+f 378//1 379//1 363//1
+f 363//1 379//1 364//1
+f 379//1 380//1 364//1
+f 364//1 380//1 365//1
+f 380//1 381//1 365//1
+f 365//1 381//1 366//1
+f 381//1 382//1 366//1
+f 366//1 382//1 367//1
+f 382//1 383//1 367//1
+f 367//1 383//1 368//1
+f 383//1 384//1 368//1
+f 368//1 384//1 369//1
+f 384//1 385//1 369//1
+f 369//1 385//1 370//1
+f 385//1 386//1 370//1
+f 370//1 386//1 371//1
+f 386//1 387//1 371//1
+f 371//1 387//1 372//1
+f 387//1 388//1 372//1
+f 372//1 388//1 373//1
+f 388//1 389//1 373//1
+f 373//1 389//1 374//1
+f 389//1 390//1 374//1
+f 374//1 390//1 189//1
+f 390//1 188//1 189//1
+f 221//1 391//1 375//1
+f 391//1 392//1 375//1
+f 375//1 392//1 376//1
+f 392//1 393//1 376//1
+f 376//1 393//1 377//1
+f 393//1 394//1 377//1
+f 377//1 394//1 378//1
+f 394//1 395//1 378//1
+f 378//1 395//1 379//1
+f 395//1 396//1 379//1
+f 379//1 396//1 380//1
+f 396//1 397//1 380//1
+f 380//1 397//1 381//1
+f 397//1 398//1 381//1
+f 381//1 398//1 382//1
+f 398//1 399//1 382//1
+f 382//1 399//1 383//1
+f 399//1 400//1 383//1
+f 383//1 400//1 384//1
+f 400//1 401//1 384//1
+f 384//1 401//1 385//1
+f 401//1 402//1 385//1
+f 385//1 402//1 386//1
+f 402//1 403//1 386//1
+f 386//1 403//1 387//1
+f 403//1 404//1 387//1
+f 387//1 404//1 388//1
+f 404//1 405//1 388//1
+f 388//1 405//1 389//1
+f 405//1 406//1 389//1
+f 389//1 406//1 390//1
+f 406//1 407//1 390//1
+f 390//1 407//1 188//1
+f 407//1 187//1 188//1
+f 222//1 408//1 391//1
+f 408//1 409//1 391//1
+f 391//1 409//1 392//1
+f 409//1 410//1 392//1
+f 392//1 410//1 393//1
+f 410//1 411//1 393//1
+f 393//1 411//1 394//1
+f 411//1 412//1 394//1
+f 394//1 412//1 395//1
+f 412//1 413//1 395//1
+f 395//1 413//1 396//1
+f 413//1 414//1 396//1
+f 396//1 414//1 397//1
+f 414//1 415//1 397//1
+f 397//1 415//1 398//1
+f 415//1 416//1 398//1
+f 398//1 416//1 399//1
+f 416//1 417//1 399//1
+f 399//1 417//1 400//1
+f 417//1 418//1 400//1
+f 400//1 418//1 401//1
+f 418//1 419//1 401//1
+f 401//1 419//1 402//1
+f 419//1 420//1 402//1
+f 402//1 420//1 403//1
+f 420//1 421//1 403//1
+f 403//1 421//1 404//1
+f 421//1 422//1 404//1
+f 404//1 422//1 405//1
+f 422//1 423//1 405//1
+f 405//1 423//1 406//1
+f 423//1 424//1 406//1
+f 406//1 424//1 407//1
+f 424//1 425//1 407//1
+f 407//1 425//1 187//1
+f 425//1 186//1 187//1
+f 223//1 426//1 408//1
+f 426//1 427//1 408//1
+f 408//1 427//1 409//1
+f 427//1 428//1 409//1
+f 409//1 428//1 410//1
+f 428//1 429//1 410//1
+f 410//1 429//1 411//1
+f 429//1 430//1 411//1
+f 411//1 430//1 412//1
+f 430//1 431//1 412//1
+f 412//1 431//1 413//1
+f 431//1 432//1 413//1
+f 413//1 432//1 414//1
+f 432//1 433//1 414//1
+f 414//1 433//1 415//1
+f 433//1 434//1 415//1
+f 415//1 434//1 416//1
+f 434//1 435//1 416//1
+f 416//1 435//1 417//1
+f 435//1 436//1 417//1
+f 417//1 436//1 418//1
+f 436//1 437//1 418//1
+f 418//1 437//1 419//1
+f 437//1 438//1 419//1
+f 419//1 438//1 420//1
+f 438//1 439//1 420//1
+f 420//1 439//1 421//1
+f 439//1 440//1 421//1
+f 421//1 440//1 422//1
+f 440//1 441//1 422//1
+f 422//1 441//1 423//1
+f 441//1 442//1 423//1
+f 423//1 442//1 424//1
+f 442//1 443//1 424//1
+f 424//1 443//1 425//1
+f 443//1 444//1 425//1
+f 425//1 444//1 186//1
+f 444//1 185//1 186//1
+f 224//1 445//1 426//1
+f 445//1 446//1 426//1
+f 426//1 446//1 427//1
+f 446//1 447//1 427//1
+f 427//1 447//1 428//1
+f 447//1 448//1 428//1
+f 428//1 448//1 429//1
+f 448//1 449//1 429//1
+f 429//1 449//1 430//1
+f 449//1 450//1 430//1
+f 430//1 450//1 431//1
+f 450//1 451//1 431//1
+f 431//1 451//1 432//1
+f 451//1 452//1 432//1
+f 432//1 452//1 433//1
+f 452//1 453//1 433//1
+f 433//1 453//1 434//1
+f 453//1 454//1 434//1
+f 434//1 454//1 435//1
+f 454//1 455//1 435//1
+f 435//1 455//1 436//1
+f 455//1 456//1 436//1
+f 436//1 456//1 437//1
+f 456//1 457//1 437//1
+f 437//1 457//1 438//1
+f 457//1 458//1 438//1
+f 438//1 458//1 439//1
+f 458//1 459//1 439//1
+f 439//1 459//1 440//1
+f 459//1 460//1 440//1
+f 440//1 460//1 441//1
+f 460//1 461//1 441//1
+f 441//1 461//1 442//1
+f 461//1 462//1 442//1
+f 442//1 462//1 443//1
+f 462//1 463//1 443//1
+f 443//1 463//1 444//1
+f 463//1 464//1 444//1
+f 444//1 464//1 185//1
+f 464//1 184//1 185//1
+f 225//1 465//1 445//1
+f 465//1 466//1 445//1
+f 445//1 466//1 446//1
+f 466//1 467//1 446//1
+f 446//1 467//1 447//1
+f 467//1 468//1 447//1
+f 447//1 468//1 448//1
+f 468//1 469//1 448//1
+f 448//1 469//1 449//1
+f 469//1 470//1 449//1
+f 449//1 470//1 450//1
+f 470//1 471//1 450//1
+f 450//1 471//1 451//1
+f 471//1 472//1 451//1
+f 451//1 472//1 452//1
+f 472//1 473//1 452//1
+f 452//1 473//1 453//1
+f 473//1 474//1 453//1
+f 453//1 474//1 454//1
+f 474//1 475//1 454//1
+f 454//1 475//1 455//1
+f 475//1 476//1 455//1
+f 455//1 476//1 456//1
+f 476//1 477//1 456//1
+f 456//1 477//1 457//1
+f 477//1 478//1 457//1
+f 457//1 478//1 458//1
+f 478//1 479//1 458//1
+f 458//1 479//1 459//1
+f 479//1 480//1 459//1
+f 459//1 480//1 460//1
+f 480//1 481//1 460//1
+f 460//1 481//1 461//1
+f 481//1 482//1 461//1
+f 461//1 482//1 462//1
+f 482//1 483//1 462//1
+f 462//1 483//1 463//1
+f 483//1 484//1 463//1
+f 463//1 484//1 464//1
+f 484//1 485//1 464//1
+f 464//1 485//1 184//1
+f 485//1 183//1 184//1
+f 226//1 486//1 465//1
+f 486//1 487//1 465//1
+f 465//1 487//1 466//1
+f 487//1 488//1 466//1
+f 466//1 488//1 467//1
+f 488//1 489//1 467//1
+f 467//1 489//1 468//1
+f 489//1 490//1 468//1
+f 468//1 490//1 469//1
+f 490//1 491//1 469//1
+f 469//1 491//1 470//1
+f 491//1 492//1 470//1
+f 470//1 492//1 471//1
+f 492//1 493//1 471//1
+f 471//1 493//1 472//1
+f 493//1 494//1 472//1
+f 472//1 494//1 473//1
+f 494//1 495//1 473//1
+f 473//1 495//1 474//1
+f 495//1 496//1 474//1
+f 474//1 496//1 475//1
+f 496//1 497//1 475//1
+f 475//1 497//1 476//1
+f 497//1 498//1 476//1
+f 476//1 498//1 477//1
+f 498//1 499//1 477//1
+f 477//1 499//1 478//1
+f 499//1 500//1 478//1
+f 478//1 500//1 479//1
+f 500//1 501//1 479//1
+f 479//1 501//1 480//1
+f 501//1 502//1 480//1
+f 480//1 502//1 481//1
+f 502//1 503//1 481//1
+f 481//1 503//1 482//1
+f 503//1 504//1 482//1
+f 482//1 504//1 483//1
+f 504//1 505//1 483//1
+f 483//1 505//1 484//1
+f 505//1 506//1 484//1
+f 484//1 506//1 485//1
+f 506//1 507//1 485//1
+f 485//1 507//1 183//1
+f 507//1 182//1 183//1
+f 227//1 508//1 486//1
+f 508//1 509//1 486//1
+f 486//1 509//1 487//1
+f 509//1 510//1 487//1
+f 487//1 510//1 488//1
+f 510//1 511//1 488//1
+f 488//1 511//1 489//1
+f 511//1 512//1 489//1
+f 489//1 512//1 490//1
+f 512//1 513//1 490//1
+f 490//1 513//1 491//1
+f 513//1 514//1 491//1
+f 491//1 514//1 492//1
+f 514//1 515//1 492//1
+f 492//1 515//1 493//1
+f 515//1 516//1 493//1
+f 493//1 516//1 494//1
+f 516//1 517//1 494//1
+f 494//1 517//1 495//1
+f 517//1 518//1 495//1
+f 495//1 518//1 496//1
+f 518//1 519//1 496//1
+f 496//1 519//1 497//1
+f 519//1 520//1 497//1
+f 497//1 520//1 498//1
+f 520//1 521//1 498//1
+f 498//1 521//1 499//1
+f 521//1 522//1 499//1
+f 499//1 522//1 500//1
+f 522//1 523//1 500//1
+f 500//1 523//1 501//1
+f 523//1 524//1 501//1
+f 501//1 524//1 502//1
+f 524//1 525//1 502//1
+f 502//1 525//1 503//1
+f 525//1 526//1 503//1
+f 503//1 526//1 504//1
+f 526//1 527//1 504//1
+f 504//1 527//1 505//1
+f 527//1 528//1 505//1
+f 505//1 528//1 506//1
+f 528//1 529//1 506//1
+f 506//1 529//1 507//1
+f 529//1 530//1 507//1
+f 507//1 530//1 182//1
+f 530//1 181//1 182//1
+f 228//1 531//1 508//1
+f 531//1 532//1 508//1
+f 508//1 532//1 509//1
+f 532//1 533//1 509//1
+f 509//1 533//1 510//1
+f 533//1 534//1 510//1
+f 510//1 534//1 511//1
+f 534//1 535//1 511//1
+f 511//1 535//1 512//1
+f 535//1 536//1 512//1
+f 512//1 536//1 513//1
+f 536//1 537//1 513//1
+f 513//1 537//1 514//1
+f 537//1 538//1 514//1
+f 514//1 538//1 515//1
+f 538//1 539//1 515//1
+f 515//1 539//1 516//1
+f 539//1 540//1 516//1
+f 516//1 540//1 517//1
+f 540//1 541//1 517//1
+f 517//1 541//1 518//1
+f 541//1 542//1 518//1
+f 518//1 542//1 519//1
+f 542//1 543//1 519//1
+f 519//1 543//1 520//1
+f 543//1 544//1 520//1
+f 520//1 544//1 521//1
+f 544//1 545//1 521//1
+f 521//1 545//1 522//1
+f 545//1 546//1 522//1
+f 522//1 546//1 523//1
+f 546//1 547//1 523//1
+f 523//1 547//1 524//1
+f 547//1 548//1 524//1
+f 524//1 548//1 525//1
+f 548//1 549//1 525//1
+f 525//1 549//1 526//1
+f 549//1 550//1 526//1
+f 526//1 550//1 527//1
+f 550//1 551//1 527//1
+f 527//1 551//1 528//1
+f 551//1 552//1 528//1
+f 528//1 552//1 529//1
+f 552//1 553//1 529//1
+f 529//1 553//1 530//1
+f 553//1 554//1 530//1
+f 530//1 554//1 181//1
+f 554//1 180//1 181//1
+f 229//1 555//1 531//1
+f 555//1 556//1 531//1
+f 531//1 556//1 532//1
+f 556//1 557//1 532//1
+f 532//1 557//1 533//1
+f 557//1 558//1 533//1
+f 533//1 558//1 534//1
+f 558//1 559//1 534//1
+f 534//1 559//1 535//1
+f 559//1 560//1 535//1
+f 535//1 560//1 536//1
+f 560//1 561//1 536//1
+f 536//1 561//1 537//1
+f 561//1 562//1 537//1
+f 537//1 562//1 538//1
+f 562//1 563//1 538//1
+f 538//1 563//1 539//1
+f 563//1 564//1 539//1
+f 539//1 564//1 540//1
+f 564//1 565//1 540//1
+f 540//1 565//1 541//1
+f 565//1 566//1 541//1
+f 541//1 566//1 542//1
+f 566//1 567//1 542//1
+f 542//1 567//1 543//1
+f 567//1 568//1 543//1
+f 543//1 568//1 544//1
+f 568//1 569//1 544//1
+f 544//1 569//1 545//1
+f 569//1 570//1 545//1
+f 545//1 570//1 546//1
+f 570//1 571//1 546//1
+f 546//1 571//1 547//1
+f 571//1 572//1 547//1
+f 547//1 572//1 548//1
+f 572//1 573//1 548//1
+f 548//1 573//1 549//1
+f 573//1 574//1 549//1
+f 549//1 574//1 550//1
+f 574//1 575//1 550//1
+f 550//1 575//1 551//1
+f 575//1 576//1 551//1
+f 551//1 576//1 552//1
+f 576//1 577//1 552//1
+f 552//1 577//1 553//1
+f 577//1 578//1 553//1
+f 553//1 578//1 554//1
+f 578//1 579//1 554//1
+f 554//1 579//1 180//1
+f 579//1 179//1 180//1
+f 230//1 580//1 555//1
+f 580//1 581//1 555//1
+f 555//1 581//1 556//1
+f 581//1 582//1 556//1
+f 556//1 582//1 557//1
+f 582//1 583//1 557//1
+f 557//1 583//1 558//1
+f 583//1 584//1 558//1
+f 558//1 584//1 559//1
+f 584//1 585//1 559//1
+f 559//1 585//1 560//1
+f 585//1 586//1 560//1
+f 560//1 586//1 561//1
+f 586//1 587//1 561//1
+f 561//1 587//1 562//1
+f 587//1 588//1 562//1
+f 562//1 588//1 563//1
+f 588//1 589//1 563//1
+f 563//1 589//1 564//1
+f 589//1 590//1 564//1
+f 564//1 590//1 565//1
+f 590//1 591//1 565//1
+f 565//1 591//1 566//1
+f 591//1 592//1 566//1
+f 566//1 592//1 567//1
+f 592//1 593//1 567//1
+f 567//1 593//1 568//1
+f 593//1 594//1 568//1
+f 568//1 594//1 569//1
+f 594//1 595//1 569//1
+f 569//1 595//1 570//1
+f 595//1 596//1 570//1
+f 570//1 596//1 571//1
+f 596//1 597//1 571//1
+f 571//1 597//1 572//1
+f 597//1 598//1 572//1
+f 572//1 598//1 573//1
+f 598//1 599//1 573//1
+f 573//1 599//1 574//1
+f 599//1 600//1 574//1
+f 574//1 600//1 575//1
+f 600//1 601//1 575//1
+f 575//1 601//1 576//1
+f 601//1 602//1 576//1
+f 576//1 602//1 577//1
+f 602//1 603//1 577//1
+f 577//1 603//1 578//1
+f 603//1 604//1 578//1
+f 578//1 604//1 579//1
+f 604//1 605//1 579//1
+f 579//1 605//1 179//1
+f 605//1 178//1 179//1
+f 231//1 606//1 580//1
+f 606//1 607//1 580//1
+f 580//1 607//1 581//1
+f 607//1 608//1 581//1
+f 581//1 608//1 582//1
+f 608//1 609//1 582//1
+f 582//1 609//1 583//1
+f 609//1 610//1 583//1
+f 583//1 610//1 584//1
+f 610//1 611//1 584//1
+f 584//1 611//1 585//1
+f 611//1 612//1 585//1
+f 585//1 612//1 586//1
+f 612//1 613//1 586//1
+f 586//1 613//1 587//1
+f 613//1 614//1 587//1
+f 587//1 614//1 588//1
+f 614//1 615//1 588//1
+f 588//1 615//1 589//1
+f 615//1 616//1 589//1
+f 589//1 616//1 590//1
+f 616//1 617//1 590//1
+f 590//1 617//1 591//1
+f 617//1 618//1 591//1
+f 591//1 618//1 592//1
+f 618//1 619//1 592//1
+f 592//1 619//1 593//1
+f 619//1 620//1 593//1
+f 593//1 620//1 594//1
+f 620//1 621//1 594//1
+f 594//1 621//1 595//1
+f 621//1 622//1 595//1
+f 595//1 622//1 596//1
+f 622//1 623//1 596//1
+f 596//1 623//1 597//1
+f 623//1 624//1 597//1
+f 597//1 624//1 598//1
+f 624//1 625//1 598//1
+f 598//1 625//1 599//1
+f 625//1 626//1 599//1
+f 599//1 626//1 600//1
+f 626//1 627//1 600//1
+f 600//1 627//1 601//1
+f 627//1 628//1 601//1
+f 601//1 628//1 602//1
+f 628//1 629//1 602//1
+f 602//1 629//1 603//1
+f 629//1 630//1 603//1
+f 603//1 630//1 604//1
+f 630//1 631//1 604//1
+f 604//1 631//1 605//1
+f 631//1 632//1 605//1
+f 605//1 632//1 178//1
+f 632//1 177//1 178//1
+f 232//1 633//1 606//1
+f 633//1 634//1 606//1
+f 606//1 634//1 607//1
+f 634//1 635//1 607//1
+f 607//1 635//1 608//1
+f 635//1 636//1 608//1
+f 608//1 636//1 609//1
+f 636//1 637//1 609//1
+f 609//1 637//1 610//1
+f 637//1 638//1 610//1
+f 610//1 638//1 611//1
+f 638//1 639//1 611//1
+f 611//1 639//1 612//1
+f 639//1 640//1 612//1
+f 612//1 640//1 613//1
+f 640//1 641//1 613//1
+f 613//1 641//1 614//1
+f 641//1 642//1 614//1
+f 614//1 642//1 615//1
+f 642//1 643//1 615//1
+f 615//1 643//1 616//1
+f 643//1 644//1 616//1
+f 616//1 644//1 617//1
+f 644//1 645//1 617//1
+f 617//1 645//1 618//1
+f 645//1 646//1 618//1
+f 618//1 646//1 619//1
+f 646//1 647//1 619//1
+f 619//1 647//1 620//1
+f 647//1 648//1 620//1
+f 620//1 648//1 621//1
+f 648//1 649//1 621//1
+f 621//1 649//1 622//1
+f 649//1 650//1 622//1
+f 622//1 650//1 623//1
+f 650//1 651//1 623//1
+f 623//1 651//1 624//1
+f 651//1 652//1 624//1
+f 624//1 652//1 625//1
+f 652//1 653//1 625//1
+f 625//1 653//1 626//1
+f 653//1 654//1 626//1
+f 626//1 654//1 627//1
+f 654//1 655//1 627//1
+f 627//1 655//1 628//1
+f 655//1 656//1 628//1
+f 628//1 656//1 629//1
+f 656//1 657//1 629//1
+f 629//1 657//1 630//1
+f 657//1 658//1 630//1
+f 630//1 658//1 631//1
+f 658//1 659//1 631//1
+f 631//1 659//1 632//1
+f 659//1 660//1 632//1
+f 632//1 660//1 177//1
+f 660//1 176//1 177//1
+f 233//1 661//1 633//1
+f 661//1 662//1 633//1
+f 633//1 662//1 634//1
+f 662//1 663//1 634//1
+f 634//1 663//1 635//1
+f 663//1 664//1 635//1
+f 635//1 664//1 636//1
+f 664//1 665//1 636//1
+f 636//1 665//1 637//1
+f 665//1 666//1 637//1
+f 637//1 666//1 638//1
+f 666//1 667//1 638//1
+f 638//1 667//1 639//1
+f 667//1 668//1 639//1
+f 639//1 668//1 640//1
+f 668//1 669//1 640//1
+f 640//1 669//1 641//1
+f 669//1 670//1 641//1
+f 641//1 670//1 642//1
+f 670//1 671//1 642//1
+f 642//1 671//1 643//1
+f 671//1 672//1 643//1
+f 643//1 672//1 644//1
+f 672//1 673//1 644//1
+f 644//1 673//1 645//1
+f 673//1 674//1 645//1
+f 645//1 674//1 646//1
+f 674//1 675//1 646//1
+f 646//1 675//1 647//1
+f 675//1 676//1 647//1
+f 647//1 676//1 648//1
+f 676//1 677//1 648//1
+f 648//1 677//1 649//1
+f 677//1 678//1 649//1
+f 649//1 678//1 650//1
+f 678//1 679//1 650//1
+f 650//1 679//1 651//1
+f 679//1 680//1 651//1
+f 651//1 680//1 652//1
+f 680//1 681//1 652//1
+f 652//1 681//1 653//1
+f 681//1 682//1 653//1
+f 653//1 682//1 654//1
+f 682//1 683//1 654//1
+f 654//1 683//1 655//1
+f 683//1 684//1 655//1
+f 655//1 684//1 656//1
+f 684//1 685//1 656//1
+f 656//1 685//1 657//1
+f 685//1 686//1 657//1
+f 657//1 686//1 658//1
+f 686//1 687//1 658//1
+f 658//1 687//1 659//1
+f 687//1 688//1 659//1
+f 659//1 688//1 660//1
+f 688//1 689//1 660//1
+f 660//1 689//1 176//1
+f 689//1 175//1 176//1
+f 234//1 690//1 661//1
+f 690//1 691//1 661//1
+f 661//1 691//1 662//1
+f 691//1 692//1 662//1
+f 662//1 692//1 663//1
+f 692//1 693//1 663//1
+f 663//1 693//1 664//1
+f 693//1 694//1 664//1
+f 664//1 694//1 665//1
+f 694//1 695//1 665//1
+f 665//1 695//1 666//1
+f 695//1 696//1 666//1
+f 666//1 696//1 667//1
+f 696//1 697//1 667//1
+f 667//1 697//1 668//1
+f 697//1 698//1 668//1
+f 668//1 698//1 669//1
+f 698//1 699//1 669//1
+f 669//1 699//1 670//1
+f 699//1 700//1 670//1
+f 670//1 700//1 671//1
+f 700//1 701//1 671//1
+f 671//1 701//1 672//1
+f 701//1 702//1 672//1
+f 672//1 702//1 673//1
+f 702//1 703//1 673//1
+f 673//1 703//1 674//1
+f 703//1 704//1 674//1
+f 674//1 704//1 675//1
+f 704//1 705//1 675//1
+f 675//1 705//1 676//1
+f 705//1 706//1 676//1
+f 676//1 706//1 677//1
+f 706//1 707//1 677//1
+f 677//1 707//1 678//1
+f 707//1 708//1 678//1
+f 678//1 708//1 679//1
+f 708//1 709//1 679//1
+f 679//1 709//1 680//1
+f 709//1 710//1 680//1
+f 680//1 710//1 681//1
+f 710//1 711//1 681//1
+f 681//1 711//1 682//1
+f 711//1 712//1 682//1
+f 682//1 712//1 683//1
+f 712//1 713//1 683//1
+f 683//1 713//1 684//1
+f 713//1 714//1 684//1
+f 684//1 714//1 685//1
+f 714//1 715//1 685//1
+f 685//1 715//1 686//1
+f 715//1 716//1 686//1
+f 686//1 716//1 687//1
+f 716//1 717//1 687//1
+f 687//1 717//1 688//1
+f 717//1 718//1 688//1
+f 688//1 718//1 689//1
+f 718//1 719//1 689//1
+f 689//1 719//1 175//1
+f 719//1 174//1 175//1
+f 235//1 720//1 690//1
+f 720//1 721//1 690//1
+f 690//1 721//1 691//1
+f 721//1 722//1 691//1
+f 691//1 722//1 692//1
+f 722//1 723//1 692//1
+f 692//1 723//1 693//1
+f 723//1 724//1 693//1
+f 693//1 724//1 694//1
+f 724//1 725//1 694//1
+f 694//1 725//1 695//1
+f 725//1 726//1 695//1
+f 695//1 726//1 696//1
+f 726//1 727//1 696//1
+f 696//1 727//1 697//1
+f 727//1 728//1 697//1
+f 697//1 728//1 698//1
+f 728//1 729//1 698//1
+f 698//1 729//1 699//1
+f 729//1 730//1 699//1
+f 699//1 730//1 700//1
+f 730//1 731//1 700//1
+f 700//1 731//1 701//1
+f 731//1 732//1 701//1
+f 701//1 732//1 702//1
+f 732//1 733//1 702//1
+f 702//1 733//1 703//1
+f 733//1 734//1 703//1
+f 703//1 734//1 704//1
+f 734//1 735//1 704//1
+f 704//1 735//1 705//1
+f 735//1 736//1 705//1
+f 705//1 736//1 706//1
+f 736//1 737//1 706//1
+f 706//1 737//1 707//1
+f 737//1 738//1 707//1
+f 707//1 738//1 708//1
+f 738//1 739//1 708//1
+f 708//1 739//1 709//1
+f 739//1 740//1 709//1
+f 709//1 740//1 710//1
+f 740//1 741//1 710//1
+f 710//1 741//1 711//1
+f 741//1 742//1 711//1
+f 711//1 742//1 712//1
+f 742//1 743//1 712//1
+f 712//1 743//1 713//1
+f 743//1 744//1 713//1
+f 713//1 744//1 714//1
+f 744//1 745//1 714//1
+f 714//1 745//1 715//1
+f 745//1 746//1 715//1
+f 715//1 746//1 716//1
+f 746//1 747//1 716//1
+f 716//1 747//1 717//1
+f 747//1 748//1 717//1
+f 717//1 748//1 718//1
+f 748//1 749//1 718//1
+f 718//1 749//1 719//1
+f 749//1 750//1 719//1
+f 719//1 750//1 174//1
+f 750//1 173//1 174//1
+f 236//1 751//1 720//1
+f 751//1 752//1 720//1
+f 720//1 752//1 721//1
+f 752//1 753//1 721//1
+f 721//1 753//1 722//1
+f 753//1 754//1 722//1
+f 722//1 754//1 723//1
+f 754//1 755//1 723//1
+f 723//1 755//1 724//1
+f 755//1 756//1 724//1
+f 724//1 756//1 725//1
+f 756//1 757//1 725//1
+f 725//1 757//1 726//1
+f 757//1 758//1 726//1
+f 726//1 758//1 727//1
+f 758//1 759//1 727//1
+f 727//1 759//1 728//1
+f 759//1 760//1 728//1
+f 728//1 760//1 729//1
+f 760//1 761//1 729//1
+f 729//1 761//1 730//1
+f 761//1 762//1 730//1
+f 730//1 762//1 731//1
+f 762//1 763//1 731//1
+f 731//1 763//1 732//1
+f 763//1 764//1 732//1
+f 732//1 764//1 733//1
+f 764//1 765//1 733//1
+f 733//1 765//1 734//1
+f 765//1 766//1 734//1
+f 734//1 766//1 735//1
+f 766//1 767//1 735//1
+f 735//1 767//1 736//1
+f 767//1 768//1 736//1
+f 736//1 768//1 737//1
+f 768//1 769//1 737//1
+f 737//1 769//1 738//1
+f 769//1 770//1 738//1
+f 738//1 770//1 739//1
+f 770//1 771//1 739//1
+f 739//1 771//1 740//1
+f 771//1 772//1 740//1
+f 740//1 772//1 741//1
+f 772//1 773//1 741//1
+f 741//1 773//1 742//1
+f 773//1 774//1 742//1
+f 742//1 774//1 743//1
+f 774//1 775//1 743//1
+f 743//1 775//1 744//1
+f 775//1 776//1 744//1
+f 744//1 776//1 745//1
+f 776//1 777//1 745//1
+f 745//1 777//1 746//1
+f 777//1 778//1 746//1
+f 746//1 778//1 747//1
+f 778//1 779//1 747//1
+f 747//1 779//1 748//1
+f 779//1 780//1 748//1
+f 748//1 780//1 749//1
+f 780//1 781//1 749//1
+f 749//1 781//1 750//1
+f 781//1 782//1 750//1
+f 750//1 782//1 173//1
+f 782//1 172//1 173//1
+f 237//1 783//1 751//1
+f 783//1 784//1 751//1
+f 751//1 784//1 752//1
+f 784//1 785//1 752//1
+f 752//1 785//1 753//1
+f 785//1 786//1 753//1
+f 753//1 786//1 754//1
+f 786//1 787//1 754//1
+f 754//1 787//1 755//1
+f 787//1 788//1 755//1
+f 755//1 788//1 756//1
+f 788//1 789//1 756//1
+f 756//1 789//1 757//1
+f 789//1 790//1 757//1
+f 757//1 790//1 758//1
+f 790//1 791//1 758//1
+f 758//1 791//1 759//1
+f 791//1 792//1 759//1
+f 759//1 792//1 760//1
+f 792//1 793//1 760//1
+f 760//1 793//1 761//1
+f 793//1 794//1 761//1
+f 761//1 794//1 762//1
+f 794//1 795//1 762//1
+f 762//1 795//1 763//1
+f 795//1 796//1 763//1
+f 763//1 796//1 764//1
+f 796//1 797//1 764//1
+f 764//1 797//1 765//1
+f 797//1 798//1 765//1
+f 765//1 798//1 766//1
+f 798//1 799//1 766//1
+f 766//1 799//1 767//1
+f 799//1 800//1 767//1
+f 767//1 800//1 768//1
+f 800//1 801//1 768//1
+f 768//1 801//1 769//1
+f 801//1 802//1 769//1
+f 769//1 802//1 770//1
+f 802//1 803//1 770//1
+f 770//1 803//1 771//1
+f 803//1 804//1 771//1
+f 771//1 804//1 772//1
+f 804//1 805//1 772//1
+f 772//1 805//1 773//1
+f 805//1 806//1 773//1
+f 773//1 806//1 774//1
+f 806//1 807//1 774//1
+f 774//1 807//1 775//1
+f 807//1 808//1 775//1
+f 775//1 808//1 776//1
+f 808//1 809//1 776//1
+f 776//1 809//1 777//1
+f 809//1 810//1 777//1
+f 777//1 810//1 778//1
+f 810//1 811//1 778//1
+f 778//1 811//1 779//1
+f 811//1 812//1 779//1
+f 779//1 812//1 780//1
+f 812//1 813//1 780//1
+f 780//1 813//1 781//1
+f 813//1 814//1 781//1
+f 781//1 814//1 782//1
+f 814//1 815//1 782//1
+f 782//1 815//1 172//1
+f 815//1 171//1 172//1
+f 238//1 816//1 783//1
+f 816//1 817//1 783//1
+f 783//1 817//1 784//1
+f 817//1 818//1 784//1
+f 784//1 818//1 785//1
+f 818//1 819//1 785//1
+f 785//1 819//1 786//1
+f 819//1 820//1 786//1
+f 786//1 820//1 787//1
+f 820//1 821//1 787//1
+f 787//1 821//1 788//1
+f 821//1 822//1 788//1
+f 788//1 822//1 789//1
+f 822//1 823//1 789//1
+f 789//1 823//1 790//1
+f 823//1 824//1 790//1
+f 790//1 824//1 791//1
+f 824//1 825//1 791//1
+f 791//1 825//1 792//1
+f 825//1 826//1 792//1
+f 792//1 826//1 793//1
+f 826//1 827//1 793//1
+f 793//1 827//1 794//1
+f 827//1 828//1 794//1
+f 794//1 828//1 795//1
+f 828//1 829//1 795//1
+f 795//1 829//1 796//1
+f 829//1 830//1 796//1
+f 796//1 830//1 797//1
+f 830//1 831//1 797//1
+f 797//1 831//1 798//1
+f 831//1 832//1 798//1
+f 798//1 832//1 799//1
+f 832//1 833//1 799//1
+f 799//1 833//1 800//1
+f 833//1 834//1 800//1
+f 800//1 834//1 801//1
+f 834//1 835//1 801//1
+f 801//1 835//1 802//1
+f 835//1 836//1 802//1
+f 802//1 836//1 803//1
+f 836//1 837//1 803//1
+f 803//1 837//1 804//1
+f 837//1 838//1 804//1
+f 804//1 838//1 805//1
+f 838//1 839//1 805//1
+f 805//1 839//1 806//1
+f 839//1 840//1 806//1
+f 806//1 840//1 807//1
+f 840//1 841//1 807//1
+f 807//1 841//1 808//1
+f 841//1 842//1 808//1
+f 808//1 842//1 809//1
+f 842//1 843//1 809//1
+f 809//1 843//1 810//1
+f 843//1 844//1 810//1
+f 810//1 844//1 811//1
+f 844//1 845//1 811//1
+f 811//1 845//1 812//1
+f 845//1 846//1 812//1
+f 812//1 846//1 813//1
+f 846//1 847//1 813//1
+f 813//1 847//1 814//1
+f 847//1 848//1 814//1
+f 814//1 848//1 815//1
+f 848//1 849//1 815//1
+f 815//1 849//1 171//1
+f 849//1 170//1 171//1
+f 239//1 850//1 816//1
+f 850//1 851//1 816//1
+f 816//1 851//1 817//1
+f 851//1 852//1 817//1
+f 817//1 852//1 818//1
+f 852//1 853//1 818//1
+f 818//1 853//1 819//1
+f 853//1 854//1 819//1
+f 819//1 854//1 820//1
+f 854//1 855//1 820//1
+f 820//1 855//1 821//1
+f 855//1 856//1 821//1
+f 821//1 856//1 822//1
+f 856//1 857//1 822//1
+f 822//1 857//1 823//1
+f 857//1 858//1 823//1
+f 823//1 858//1 824//1
+f 858//1 859//1 824//1
+f 824//1 859//1 825//1
+f 859//1 860//1 825//1
+f 825//1 860//1 826//1
+f 860//1 861//1 826//1
+f 826//1 861//1 827//1
+f 861//1 862//1 827//1
+f 827//1 862//1 828//1
+f 862//1 863//1 828//1
+f 828//1 863//1 829//1
+f 863//1 864//1 829//1
+f 829//1 864//1 830//1
+f 864//1 865//1 830//1
+f 830//1 865//1 831//1
+f 865//1 866//1 831//1
+f 831//1 866//1 832//1
+f 866//1 867//1 832//1
+f 832//1 867//1 833//1
+f 867//1 868//1 833//1
+f 833//1 868//1 834//1
+f 868//1 869//1 834//1
+f 834//1 869//1 835//1
+f 869//1 870//1 835//1
+f 835//1 870//1 836//1
+f 870//1 871//1 836//1
+f 836//1 871//1 837//1
+f 871//1 872//1 837//1
+f 837//1 872//1 838//1
+f 872//1 873//1 838//1
+f 838//1 873//1 839//1
+f 873//1 874//1 839//1
+f 839//1 874//1 840//1
+f 874//1 875//1 840//1
+f 840//1 875//1 841//1
+f 875//1 876//1 841//1
+f 841//1 876//1 842//1
+f 876//1 877//1 842//1
+f 842//1 877//1 843//1
+f 877//1 878//1 843//1
+f 843//1 878//1 844//1
+f 878//1 879//1 844//1
+f 844//1 879//1 845//1
+f 879//1 880//1 845//1
+f 845//1 880//1 846//1
+f 880//1 881//1 846//1
+f 846//1 881//1 847//1
+f 881//1 882//1 847//1
+f 847//1 882//1 848//1
+f 882//1 883//1 848//1
+f 848//1 883//1 849//1
+f 883//1 884//1 849//1
+f 849//1 884//1 170//1
+f 884//1 169//1 170//1
+f 240//1 885//1 850//1
+f 885//1 886//1 850//1
+f 850//1 886//1 851//1
+f 886//1 887//1 851//1
+f 851//1 887//1 852//1
+f 887//1 888//1 852//1
+f 852//1 888//1 853//1
+f 888//1 889//1 853//1
+f 853//1 889//1 854//1
+f 889//1 890//1 854//1
+f 854//1 890//1 855//1
+f 890//1 891//1 855//1
+f 855//1 891//1 856//1
+f 891//1 892//1 856//1
+f 856//1 892//1 857//1
+f 892//1 893//1 857//1
+f 857//1 893//1 858//1
+f 893//1 894//1 858//1
+f 858//1 894//1 859//1
+f 894//1 895//1 859//1
+f 859//1 895//1 860//1
+f 895//1 896//1 860//1
+f 860//1 896//1 861//1
+f 896//1 897//1 861//1
+f 861//1 897//1 862//1
+f 897//1 898//1 862//1
+f 862//1 898//1 863//1
+f 898//1 899//1 863//1
+f 863//1 899//1 864//1
+f 899//1 900//1 864//1
+f 864//1 900//1 865//1
+f 900//1 901//1 865//1
+f 865//1 901//1 866//1
+f 901//1 902//1 866//1
+f 866//1 902//1 867//1
+f 902//1 903//1 867//1
+f 867//1 903//1 868//1
+f 903//1 904//1 868//1
+f 868//1 904//1 869//1
+f 904//1 905//1 869//1
+f 869//1 905//1 870//1
+f 905//1 906//1 870//1
+f 870//1 906//1 871//1
+f 906//1 907//1 871//1
+f 871//1 907//1 872//1
+f 907//1 908//1 872//1
+f 872//1 908//1 873//1
+f 908//1 909//1 873//1
+f 873//1 909//1 874//1
+f 909//1 910//1 874//1
+f 874//1 910//1 875//1
+f 910//1 911//1 875//1
+f 875//1 911//1 876//1
+f 911//1 912//1 876//1
+f 876//1 912//1 877//1
+f 912//1 913//1 877//1
+f 877//1 913//1 878//1
+f 913//1 914//1 878//1
+f 878//1 914//1 879//1
+f 914//1 915//1 879//1
+f 879//1 915//1 880//1
+f 915//1 916//1 880//1
+f 880//1 916//1 881//1
+f 916//1 917//1 881//1
+f 881//1 917//1 882//1
+f 917//1 918//1 882//1
+f 882//1 918//1 883//1
+f 918//1 919//1 883//1
+f 883//1 919//1 884//1
+f 919//1 920//1 884//1
+f 884//1 920//1 169//1
+f 920//1 168//1 169//1
+f 241//1 921//1 885//1
+f 921//1 922//1 885//1
+f 885//1 922//1 886//1
+f 922//1 923//1 886//1
+f 886//1 923//1 887//1
+f 923//1 924//1 887//1
+f 887//1 924//1 888//1
+f 924//1 925//1 888//1
+f 888//1 925//1 889//1
+f 925//1 926//1 889//1
+f 889//1 926//1 890//1
+f 926//1 927//1 890//1
+f 890//1 927//1 891//1
+f 927//1 928//1 891//1
+f 891//1 928//1 892//1
+f 928//1 929//1 892//1
+f 892//1 929//1 893//1
+f 929//1 930//1 893//1
+f 893//1 930//1 894//1
+f 930//1 931//1 894//1
+f 894//1 931//1 895//1
+f 931//1 932//1 895//1
+f 895//1 932//1 896//1
+f 932//1 933//1 896//1
+f 896//1 933//1 897//1
+f 933//1 934//1 897//1
+f 897//1 934//1 898//1
+f 934//1 935//1 898//1
+f 898//1 935//1 899//1
+f 935//1 936//1 899//1
+f 899//1 936//1 900//1
+f 936//1 937//1 900//1
+f 900//1 937//1 901//1
+f 937//1 938//1 901//1
+f 901//1 938//1 902//1
+f 938//1 939//1 902//1
+f 902//1 939//1 903//1
+f 939//1 940//1 903//1
+f 903//1 940//1 904//1
+f 940//1 941//1 904//1
+f 904//1 941//1 905//1
+f 941//1 942//1 905//1
+f 905//1 942//1 906//1
+f 942//1 943//1 906//1
+f 906//1 943//1 907//1
+f 943//1 944//1 907//1
+f 907//1 944//1 908//1
+f 944//1 945//1 908//1
+f 908//1 945//1 909//1
+f 945//1 946//1 909//1
+f 909//1 946//1 910//1
+f 946//1 947//1 910//1
+f 910//1 947//1 911//1
+f 947//1 948//1 911//1
+f 911//1 948//1 912//1
+f 948//1 949//1 912//1
+f 912//1 949//1 913//1
+f 949//1 950//1 913//1
+f 913//1 950//1 914//1
+f 950//1 951//1 914//1
+f 914//1 951//1 915//1
+f 951//1 952//1 915//1
+f 915//1 952//1 916//1
+f 952//1 953//1 916//1
+f 916//1 953//1 917//1
+f 953//1 954//1 917//1
+f 917//1 954//1 918//1
+f 954//1 955//1 918//1
+f 918//1 955//1 919//1
+f 955//1 956//1 919//1
+f 919//1 956//1 920//1
+f 956//1 957//1 920//1
+f 920//1 957//1 168//1
+f 957//1 167//1 168//1
+f 242//1 958//1 921//1
+f 958//1 959//1 921//1
+f 921//1 959//1 922//1
+f 959//1 960//1 922//1
+f 922//1 960//1 923//1
+f 960//1 961//1 923//1
+f 923//1 961//1 924//1
+f 961//1 962//1 924//1
+f 924//1 962//1 925//1
+f 962//1 963//1 925//1
+f 925//1 963//1 926//1
+f 963//1 964//1 926//1
+f 926//1 964//1 927//1
+f 964//1 965//1 927//1
+f 927//1 965//1 928//1
+f 965//1 966//1 928//1
+f 928//1 966//1 929//1
+f 966//1 967//1 929//1
+f 929//1 967//1 930//1
+f 967//1 968//1 930//1
+f 930//1 968//1 931//1
+f 968//1 969//1 931//1
+f 931//1 969//1 932//1
+f 969//1 970//1 932//1
+f 932//1 970//1 933//1
+f 970//1 971//1 933//1
+f 933//1 971//1 934//1
+f 971//1 972//1 934//1
+f 934//1 972//1 935//1
+f 972//1 973//1 935//1
+f 935//1 973//1 936//1
+f 973//1 974//1 936//1
+f 936//1 974//1 937//1
+f 974//1 975//1 937//1
+f 937//1 975//1 938//1
+f 975//1 976//1 938//1
+f 938//1 976//1 939//1
+f 976//1 977//1 939//1
+f 939//1 977//1 940//1
+f 977//1 978//1 940//1
+f 940//1 978//1 941//1
+f 978//1 979//1 941//1
+f 941//1 979//1 942//1
+f 979//1 980//1 942//1
+f 942//1 980//1 943//1
+f 980//1 981//1 943//1
+f 943//1 981//1 944//1
+f 981//1 982//1 944//1
+f 944//1 982//1 945//1
+f 982//1 983//1 945//1
+f 945//1 983//1 946//1
+f 983//1 984//1 946//1
+f 946//1 984//1 947//1
+f 984//1 985//1 947//1
+f 947//1 985//1 948//1
+f 985//1 986//1 948//1
+f 948//1 986//1 949//1
+f 986//1 987//1 949//1
+f 949//1 987//1 950//1
+f 987//1 988//1 950//1
+f 950//1 988//1 951//1
+f 988//1 989//1 951//1
+f 951//1 989//1 952//1
+f 989//1 990//1 952//1
+f 952//1 990//1 953//1
+f 990//1 991//1 953//1
+f 953//1 991//1 954//1
+f 991//1 992//1 954//1
+f 954//1 992//1 955//1
+f 992//1 993//1 955//1
+f 955//1 993//1 956//1
+f 993//1 994//1 956//1
+f 956//1 994//1 957//1
+f 994//1 995//1 957//1
+f 957//1 995//1 167//1
+f 995//1 166//1 167//1
+f 243//1 996//1 958//1
+f 996//1 997//1 958//1
+f 958//1 997//1 959//1
+f 997//1 998//1 959//1
+f 959//1 998//1 960//1
+f 998//1 999//1 960//1
+f 960//1 999//1 961//1
+f 999//1 1000//1 961//1
+f 961//1 1000//1 962//1
+f 1000//1 1001//1 962//1
+f 962//1 1001//1 963//1
+f 1001//1 1002//1 963//1
+f 963//1 1002//1 964//1
+f 1002//1 1003//1 964//1
+f 964//1 1003//1 965//1
+f 1003//1 1004//1 965//1
+f 965//1 1004//1 966//1
+f 1004//1 1005//1 966//1
+f 966//1 1005//1 967//1
+f 1005//1 1006//1 967//1
+f 967//1 1006//1 968//1
+f 1006//1 1007//1 968//1
+f 968//1 1007//1 969//1
+f 1007//1 1008//1 969//1
+f 969//1 1008//1 970//1
+f 1008//1 1009//1 970//1
+f 970//1 1009//1 971//1
+f 1009//1 1010//1 971//1
+f 971//1 1010//1 972//1
+f 1010//1 1011//1 972//1
+f 972//1 1011//1 973//1
+f 1011//1 1012//1 973//1
+f 973//1 1012//1 974//1
+f 1012//1 1013//1 974//1
+f 974//1 1013//1 975//1
+f 1013//1 1014//1 975//1
+f 975//1 1014//1 976//1
+f 1014//1 1015//1 976//1
+f 976//1 1015//1 977//1
+f 1015//1 1016//1 977//1
+f 977//1 1016//1 978//1
+f 1016//1 1017//1 978//1
+f 978//1 1017//1 979//1
+f 1017//1 1018//1 979//1
+f 979//1 1018//1 980//1
+f 1018//1 1019//1 980//1
+f 980//1 1019//1 981//1
+f 1019//1 1020//1 981//1
+f 981//1 1020//1 982//1
+f 1020//1 1021//1 982//1
+f 982//1 1021//1 983//1
+f 1021//1 1022//1 983//1
+f 983//1 1022//1 984//1
+f 1022//1 1023//1 984//1
+f 984//1 1023//1 985//1
+f 1023//1 1024//1 985//1
+f 985//1 1024//1 986//1
+f 1024//1 1025//1 986//1
+f 986//1 1025//1 987//1
+f 1025//1 1026//1 987//1
+f 987//1 1026//1 988//1
+f 1026//1 1027//1 988//1
+f 988//1 1027//1 989//1
+f 1027//1 1028//1 989//1
+f 989//1 1028//1 990//1
+f 1028//1 1029//1 990//1
+f 990//1 1029//1 991//1
+f 1029//1 1030//1 991//1
+f 991//1 1030//1 992//1
+f 1030//1 1031//1 992//1
+f 992//1 1031//1 993//1
+f 1031//1 1032//1 993//1
+f 993//1 1032//1 994//1
+f 1032//1 1033//1 994//1
+f 994//1 1033//1 995//1
+f 1033//1 1034//1 995//1
+f 995//1 1034//1 166//1
+f 1034//1 165//1 166//1
+f 244//1 1035//1 996//1
+f 1035//1 1036//1 996//1
+f 996//1 1036//1 997//1
+f 1036//1 1037//1 997//1
+f 997//1 1037//1 998//1
+f 1037//1 1038//1 998//1
+f 998//1 1038//1 999//1
+f 1038//1 1039//1 999//1
+f 999//1 1039//1 1000//1
+f 1039//1 1040//1 1000//1
+f 1000//1 1040//1 1001//1
+f 1040//1 1041//1 1001//1
+f 1001//1 1041//1 1002//1
+f 1041//1 1042//1 1002//1
+f 1002//1 1042//1 1003//1
+f 1042//1 1043//1 1003//1
+f 1003//1 1043//1 1004//1
+f 1043//1 1044//1 1004//1
+f 1004//1 1044//1 1005//1
+f 1044//1 1045//1 1005//1
+f 1005//1 1045//1 1006//1
+f 1045//1 1046//1 1006//1
+f 1006//1 1046//1 1007//1
+f 1046//1 1047//1 1007//1
+f 1007//1 1047//1 1008//1
+f 1047//1 1048//1 1008//1
+f 1008//1 1048//1 1009//1
+f 1048//1 1049//1 1009//1
+f 1009//1 1049//1 1010//1
+f 1049//1 1050//1 1010//1
+f 1010//1 1050//1 1011//1
+f 1050//1 1051//1 1011//1
+f 1011//1 1051//1 1012//1
+f 1051//1 1052//1 1012//1
+f 1012//1 1052//1 1013//1
+f 1052//1 1053//1 1013//1
+f 1013//1 1053//1 1014//1
+f 1053//1 1054//1 1014//1
+f 1014//1 1054//1 1015//1
+f 1054//1 1055//1 1015//1
+f 1015//1 1055//1 1016//1
+f 1055//1 1056//1 1016//1
+f 1016//1 1056//1 1017//1
+f 1056//1 1057//1 1017//1
+f 1017//1 1057//1 1018//1
+f 1057//1 1058//1 1018//1
+f 1018//1 1058//1 1019//1
+f 1058//1 1059//1 1019//1
+f 1019//1 1059//1 1020//1
+f 1059//1 1060//1 1020//1
+f 1020//1 1060//1 1021//1
+f 1060//1 1061//1 1021//1
+f 1021//1 1061//1 1022//1
+f 1061//1 1062//1 1022//1
+f 1022//1 1062//1 1023//1
+f 1062//1 1063//1 1023//1
+f 1023//1 1063//1 1024//1
+f 1063//1 1064//1 1024//1
+f 1024//1 1064//1 1025//1
+f 1064//1 1065//1 1025//1
+f 1025//1 1065//1 1026//1
+f 1065//1 1066//1 1026//1
+f 1026//1 1066//1 1027//1
+f 1066//1 1067//1 1027//1
+f 1027//1 1067//1 1028//1
+f 1067//1 1068//1 1028//1
+f 1028//1 1068//1 1029//1
+f 1068//1 1069//1 1029//1
+f 1029//1 1069//1 1030//1
+f 1069//1 1070//1 1030//1
+f 1030//1 1070//1 1031//1
+f 1070//1 1071//1 1031//1
+f 1031//1 1071//1 1032//1
+f 1071//1 1072//1 1032//1
+f 1032//1 1072//1 1033//1
+f 1072//1 1073//1 1033//1
+f 1033//1 1073//1 1034//1
+f 1073//1 1074//1 1034//1
+f 1034//1 1074//1 165//1
+f 1074//1 164//1 165//1
+f 245//1 1075//1 1035//1
+f 1075//1 1076//1 1035//1
+f 1035//1 1076//1 1036//1
+f 1076//1 1077//1 1036//1
+f 1036//1 1077//1 1037//1
+f 1077//1 1078//1 1037//1
+f 1037//1 1078//1 1038//1
+f 1078//1 1079//1 1038//1
+f 1038//1 1079//1 1039//1
+f 1079//1 1080//1 1039//1
+f 1039//1 1080//1 1040//1
+f 1080//1 1081//1 1040//1
+f 1040//1 1081//1 1041//1
+f 1081//1 1082//1 1041//1
+f 1041//1 1082//1 1042//1
+f 1082//1 1083//1 1042//1
+f 1042//1 1083//1 1043//1
+f 1083//1 1084//1 1043//1
+f 1043//1 1084//1 1044//1
+f 1084//1 1085//1 1044//1
+f 1044//1 1085//1 1045//1
+f 1085//1 1086//1 1045//1
+f 1045//1 1086//1 1046//1
+f 1086//1 1087//1 1046//1
+f 1046//1 1087//1 1047//1
+f 1087//1 1088//1 1047//1
+f 1047//1 1088//1 1048//1
+f 1088//1 1089//1 1048//1
+f 1048//1 1089//1 1049//1
+f 1089//1 1090//1 1049//1
+f 1049//1 1090//1 1050//1
+f 1090//1 1091//1 1050//1
+f 1050//1 1091//1 1051//1
+f 1091//1 1092//1 1051//1
+f 1051//1 1092//1 1052//1
+f 1092//1 1093//1 1052//1
+f 1052//1 1093//1 1053//1
+f 1093//1 1094//1 1053//1
+f 1053//1 1094//1 1054//1
+f 1094//1 1095//1 1054//1
+f 1054//1 1095//1 1055//1
+f 1095//1 1096//1 1055//1
+f 1055//1 1096//1 1056//1
+f 1096//1 1097//1 1056//1
+f 1056//1 1097//1 1057//1
+f 1097//1 1098//1 1057//1
+f 1057//1 1098//1 1058//1
+f 1098//1 1099//1 1058//1
+f 1058//1 1099//1 1059//1
+f 1099//1 1100//1 1059//1
+f 1059//1 1100//1 1060//1
+f 1100//1 1101//1 1060//1
+f 1060//1 1101//1 1061//1
+f 1101//1 1102//1 1061//1
+f 1061//1 1102//1 1062//1
+f 1102//1 1103//1 1062//1
+f 1062//1 1103//1 1063//1
+f 1103//1 1104//1 1063//1
+f 1063//1 1104//1 1064//1
+f 1104//1 1105//1 1064//1
+f 1064//1 1105//1 1065//1
+f 1105//1 1106//1 1065//1
+f 1065//1 1106//1 1066//1
+f 1106//1 1107//1 1066//1
+f 1066//1 1107//1 1067//1
+f 1107//1 1108//1 1067//1
+f 1067//1 1108//1 1068//1
+f 1108//1 1109//1 1068//1
+f 1068//1 1109//1 1069//1
+f 1109//1 1110//1 1069//1
+f 1069//1 1110//1 1070//1
+f 1110//1 1111//1 1070//1
+f 1070//1 1111//1 1071//1
+f 1111//1 1112//1 1071//1
+f 1071//1 1112//1 1072//1
+f 1112//1 1113//1 1072//1
+f 1072//1 1113//1 1073//1
+f 1113//1 1114//1 1073//1
+f 1073//1 1114//1 1074//1
+f 1114//1 1115//1 1074//1
+f 1074//1 1115//1 164//1
+f 1115//1 163//1 164//1
+f 246//1 1116//1 1075//1
+f 1116//1 1117//1 1075//1
+f 1075//1 1117//1 1076//1
+f 1117//1 1118//1 1076//1
+f 1076//1 1118//1 1077//1
+f 1118//1 1119//1 1077//1
+f 1077//1 1119//1 1078//1
+f 1119//1 1120//1 1078//1
+f 1078//1 1120//1 1079//1
+f 1120//1 1121//1 1079//1
+f 1079//1 1121//1 1080//1
+f 1121//1 1122//1 1080//1
+f 1080//1 1122//1 1081//1
+f 1122//1 1123//1 1081//1
+f 1081//1 1123//1 1082//1
+f 1123//1 1124//1 1082//1
+f 1082//1 1124//1 1083//1
+f 1124//1 1125//1 1083//1
+f 1083//1 1125//1 1084//1
+f 1125//1 1126//1 1084//1
+f 1084//1 1126//1 1085//1
+f 1126//1 1127//1 1085//1
+f 1085//1 1127//1 1086//1
+f 1127//1 1128//1 1086//1
+f 1086//1 1128//1 1087//1
+f 1128//1 1129//1 1087//1
+f 1087//1 1129//1 1088//1
+f 1129//1 1130//1 1088//1
+f 1088//1 1130//1 1089//1
+f 1130//1 1131//1 1089//1
+f 1089//1 1131//1 1090//1
+f 1131//1 1132//1 1090//1
+f 1090//1 1132//1 1091//1
+f 1132//1 1133//1 1091//1
+f 1091//1 1133//1 1092//1
+f 1133//1 1134//1 1092//1
+f 1092//1 1134//1 1093//1
+f 1134//1 1135//1 1093//1
+f 1093//1 1135//1 1094//1
+f 1135//1 1136//1 1094//1
+f 1094//1 1136//1 1095//1
+f 1136//1 1137//1 1095//1
+f 1095//1 1137//1 1096//1
+f 1137//1 1138//1 1096//1
+f 1096//1 1138//1 1097//1
+f 1138//1 1139//1 1097//1
+f 1097//1 1139//1 1098//1
+f 1139//1 1140//1 1098//1
+f 1098//1 1140//1 1099//1
+f 1140//1 1141//1 1099//1
+f 1099//1 1141//1 1100//1
+f 1141//1 1142//1 1100//1
+f 1100//1 1142//1 1101//1
+f 1142//1 1143//1 1101//1
+f 1101//1 1143//1 1102//1
+f 1143//1 1144//1 1102//1
+f 1102//1 1144//1 1103//1
+f 1144//1 1145//1 1103//1
+f 1103//1 1145//1 1104//1
+f 1145//1 1146//1 1104//1
+f 1104//1 1146//1 1105//1
+f 1146//1 1147//1 1105//1
+f 1105//1 1147//1 1106//1
+f 1147//1 1148//1 1106//1
+f 1106//1 1148//1 1107//1
+f 1148//1 1149//1 1107//1
+f 1107//1 1149//1 1108//1
+f 1149//1 1150//1 1108//1
+f 1108//1 1150//1 1109//1
+f 1150//1 1151//1 1109//1
+f 1109//1 1151//1 1110//1
+f 1151//1 1152//1 1110//1
+f 1110//1 1152//1 1111//1
+f 1152//1 1153//1 1111//1
+f 1111//1 1153//1 1112//1
+f 1153//1 1154//1 1112//1
+f 1112//1 1154//1 1113//1
+f 1154//1 1155//1 1113//1
+f 1113//1 1155//1 1114//1
+f 1155//1 1156//1 1114//1
+f 1114//1 1156//1 1115//1
+f 1156//1 1157//1 1115//1
+f 1115//1 1157//1 163//1
+f 1157//1 162//1 163//1
+f 247//1 1158//1 1116//1
+f 1158//1 1159//1 1116//1
+f 1116//1 1159//1 1117//1
+f 1159//1 1160//1 1117//1
+f 1117//1 1160//1 1118//1
+f 1160//1 1161//1 1118//1
+f 1118//1 1161//1 1119//1
+f 1161//1 1162//1 1119//1
+f 1119//1 1162//1 1120//1
+f 1162//1 1163//1 1120//1
+f 1120//1 1163//1 1121//1
+f 1163//1 1164//1 1121//1
+f 1121//1 1164//1 1122//1
+f 1164//1 1165//1 1122//1
+f 1122//1 1165//1 1123//1
+f 1165//1 1166//1 1123//1
+f 1123//1 1166//1 1124//1
+f 1166//1 1167//1 1124//1
+f 1124//1 1167//1 1125//1
+f 1167//1 1168//1 1125//1
+f 1125//1 1168//1 1126//1
+f 1168//1 1169//1 1126//1
+f 1126//1 1169//1 1127//1
+f 1169//1 1170//1 1127//1
+f 1127//1 1170//1 1128//1
+f 1170//1 1171//1 1128//1
+f 1128//1 1171//1 1129//1
+f 1171//1 1172//1 1129//1
+f 1129//1 1172//1 1130//1
+f 1172//1 1173//1 1130//1
+f 1130//1 1173//1 1131//1
+f 1173//1 1174//1 1131//1
+f 1131//1 1174//1 1132//1
+f 1174//1 1175//1 1132//1
+f 1132//1 1175//1 1133//1
+f 1175//1 1176//1 1133//1
+f 1133//1 1176//1 1134//1
+f 1176//1 1177//1 1134//1
+f 1134//1 1177//1 1135//1
+f 1177//1 1178//1 1135//1
+f 1135//1 1178//1 1136//1
+f 1178//1 1179//1 1136//1
+f 1136//1 1179//1 1137//1
+f 1179//1 1180//1 1137//1
+f 1137//1 1180//1 1138//1
+f 1180//1 1181//1 1138//1
+f 1138//1 1181//1 1139//1
+f 1181//1 1182//1 1139//1
+f 1139//1 1182//1 1140//1
+f 1182//1 1183//1 1140//1
+f 1140//1 1183//1 1141//1
+f 1183//1 1184//1 1141//1
+f 1141//1 1184//1 1142//1
+f 1184//1 1185//1 1142//1
+f 1142//1 1185//1 1143//1
+f 1185//1 1186//1 1143//1
+f 1143//1 1186//1 1144//1
+f 1186//1 1187//1 1144//1
+f 1144//1 1187//1 1145//1
+f 1187//1 1188//1 1145//1
+f 1145//1 1188//1 1146//1
+f 1188//1 1189//1 1146//1
+f 1146//1 1189//1 1147//1
+f 1189//1 1190//1 1147//1
+f 1147//1 1190//1 1148//1
+f 1190//1 1191//1 1148//1
+f 1148//1 1191//1 1149//1
+f 1191//1 1192//1 1149//1
+f 1149//1 1192//1 1150//1
+f 1192//1 1193//1 1150//1
+f 1150//1 1193//1 1151//1
+f 1193//1 1194//1 1151//1
+f 1151//1 1194//1 1152//1
+f 1194//1 1195//1 1152//1
+f 1152//1 1195//1 1153//1
+f 1195//1 1196//1 1153//1
+f 1153//1 1196//1 1154//1
+f 1196//1 1197//1 1154//1
+f 1154//1 1197//1 1155//1
+f 1197//1 1198//1 1155//1
+f 1155//1 1198//1 1156//1
+f 1198//1 1199//1 1156//1
+f 1156//1 1199//1 1157//1
+f 1199//1 1200//1 1157//1
+f 1157//1 1200//1 162//1
+f 1200//1 161//1 162//1
+f 248//1 1201//1 1158//1
+f 1201//1 1202//1 1158//1
+f 1158//1 1202//1 1159//1
+f 1202//1 1203//1 1159//1
+f 1159//1 1203//1 1160//1
+f 1203//1 1204//1 1160//1
+f 1160//1 1204//1 1161//1
+f 1204//1 1205//1 1161//1
+f 1161//1 1205//1 1162//1
+f 1205//1 1206//1 1162//1
+f 1162//1 1206//1 1163//1
+f 1206//1 1207//1 1163//1
+f 1163//1 1207//1 1164//1
+f 1207//1 1208//1 1164//1
+f 1164//1 1208//1 1165//1
+f 1208//1 1209//1 1165//1
+f 1165//1 1209//1 1166//1
+f 1209//1 1210//1 1166//1
+f 1166//1 1210//1 1167//1
+f 1210//1 1211//1 1167//1
+f 1167//1 1211//1 1168//1
+f 1211//1 1212//1 1168//1
+f 1168//1 1212//1 1169//1
+f 1212//1 1213//1 1169//1
+f 1169//1 1213//1 1170//1
+f 1213//1 1214//1 1170//1
+f 1170//1 1214//1 1171//1
+f 1214//1 1215//1 1171//1
+f 1171//1 1215//1 1172//1
+f 1215//1 1216//1 1172//1
+f 1172//1 1216//1 1173//1
+f 1216//1 1217//1 1173//1
+f 1173//1 1217//1 1174//1
+f 1217//1 1218//1 1174//1
+f 1174//1 1218//1 1175//1
+f 1218//1 1219//1 1175//1
+f 1175//1 1219//1 1176//1
+f 1219//1 1220//1 1176//1
+f 1176//1 1220//1 1177//1
+f 1220//1 1221//1 1177//1
+f 1177//1 1221//1 1178//1
+f 1221//1 1222//1 1178//1
+f 1178//1 1222//1 1179//1
+f 1222//1 1223//1 1179//1
+f 1179//1 1223//1 1180//1
+f 1223//1 1224//1 1180//1
+f 1180//1 1224//1 1181//1
+f 1224//1 1225//1 1181//1
+f 1181//1 1225//1 1182//1
+f 1225//1 1226//1 1182//1
+f 1182//1 1226//1 1183//1
+f 1226//1 1227//1 1183//1
+f 1183//1 1227//1 1184//1
+f 1227//1 1228//1 1184//1
+f 1184//1 1228//1 1185//1
+f 1228//1 1229//1 1185//1
+f 1185//1 1229//1 1186//1
+f 1229//1 1230//1 1186//1
+f 1186//1 1230//1 1187//1
+f 1230//1 1231//1 1187//1
+f 1187//1 1231//1 1188//1
+f 1231//1 1232//1 1188//1
+f 1188//1 1232//1 1189//1
+f 1232//1 1233//1 1189//1
+f 1189//1 1233//1 1190//1
+f 1233//1 1234//1 1190//1
+f 1190//1 1234//1 1191//1
+f 1234//1 1235//1 1191//1
+f 1191//1 1235//1 1192//1
+f 1235//1 1236//1 1192//1
+f 1192//1 1236//1 1193//1
+f 1236//1 1237//1 1193//1
+f 1193//1 1237//1 1194//1
+f 1237//1 1238//1 1194//1
+f 1194//1 1238//1 1195//1
+f 1238//1 1239//1 1195//1
+f 1195//1 1239//1 1196//1
+f 1239//1 1240//1 1196//1
+f 1196//1 1240//1 1197//1
+f 1240//1 1241//1 1197//1
+f 1197//1 1241//1 1198//1
+f 1241//1 1242//1 1198//1
+f 1198//1 1242//1 1199//1
+f 1242//1 1243//1 1199//1
+f 1199//1 1243//1 1200//1
+f 1243//1 1244//1 1200//1
+f 1200//1 1244//1 161//1
+f 1244//1 160//1 161//1
+f 249//1 1245//1 1201//1
+f 1245//1 1246//1 1201//1
+f 1201//1 1246//1 1202//1
+f 1246//1 1247//1 1202//1
+f 1202//1 1247//1 1203//1
+f 1247//1 1248//1 1203//1
+f 1203//1 1248//1 1204//1
+f 1248//1 1249//1 1204//1
+f 1204//1 1249//1 1205//1
+f 1249//1 1250//1 1205//1
+f 1205//1 1250//1 1206//1
+f 1250//1 1251//1 1206//1
+f 1206//1 1251//1 1207//1
+f 1251//1 1252//1 1207//1
+f 1207//1 1252//1 1208//1
+f 1252//1 1253//1 1208//1
+f 1208//1 1253//1 1209//1
+f 1253//1 1254//1 1209//1
+f 1209//1 1254//1 1210//1
+f 1254//1 1255//1 1210//1
+f 1210//1 1255//1 1211//1
+f 1255//1 1256//1 1211//1
+f 1211//1 1256//1 1212//1
+f 1256//1 1257//1 1212//1
+f 1212//1 1257//1 1213//1
+f 1257//1 1258//1 1213//1
+f 1213//1 1258//1 1214//1
+f 1258//1 1259//1 1214//1
+f 1214//1 1259//1 1215//1
+f 1259//1 1260//1 1215//1
+f 1215//1 1260//1 1216//1
+f 1260//1 1261//1 1216//1
+f 1216//1 1261//1 1217//1
+f 1261//1 1262//1 1217//1
+f 1217//1 1262//1 1218//1
+f 1262//1 1263//1 1218//1
+f 1218//1 1263//1 1219//1
+f 1263//1 1264//1 1219//1
+f 1219//1 1264//1 1220//1
+f 1264//1 1265//1 1220//1
+f 1220//1 1265//1 1221//1
+f 1265//1 1266//1 1221//1
+f 1221//1 1266//1 1222//1
+f 1266//1 1267//1 1222//1
+f 1222//1 1267//1 1223//1
+f 1267//1 1268//1 1223//1
+f 1223//1 1268//1 1224//1
+f 1268//1 1269//1 1224//1
+f 1224//1 1269//1 1225//1
+f 1269//1 1270//1 1225//1
+f 1225//1 1270//1 1226//1
+f 1270//1 1271//1 1226//1
+f 1226//1 1271//1 1227//1
+f 1271//1 1272//1 1227//1
+f 1227//1 1272//1 1228//1
+f 1272//1 1273//1 1228//1
+f 1228//1 1273//1 1229//1
+f 1273//1 1274//1 1229//1
+f 1229//1 1274//1 1230//1
+f 1274//1 1275//1 1230//1
+f 1230//1 1275//1 1231//1
+f 1275//1 1276//1 1231//1
+f 1231//1 1276//1 1232//1
+f 1276//1 1277//1 1232//1
+f 1232//1 1277//1 1233//1
+f 1277//1 1278//1 1233//1
+f 1233//1 1278//1 1234//1
+f 1278//1 1279//1 1234//1
+f 1234//1 1279//1 1235//1
+f 1279//1 1280//1 1235//1
+f 1235//1 1280//1 1236//1
+f 1280//1 1281//1 1236//1
+f 1236//1 1281//1 1237//1
+f 1281//1 1282//1 1237//1
+f 1237//1 1282//1 1238//1
+f 1282//1 1283//1 1238//1
+f 1238//1 1283//1 1239//1
+f 1283//1 1284//1 1239//1
+f 1239//1 1284//1 1240//1
+f 1284//1 1285//1 1240//1
+f 1240//1 1285//1 1241//1
+f 1285//1 1286//1 1241//1
+f 1241//1 1286//1 1242//1
+f 1286//1 1287//1 1242//1
+f 1242//1 1287//1 1243//1
+f 1287//1 1288//1 1243//1
+f 1243//1 1288//1 1244//1
+f 1288//1 1289//1 1244//1
+f 1244//1 1289//1 160//1
+f 1289//1 159//1 160//1
+f 250//1 1290//1 1245//1
+f 1290//1 1291//1 1245//1
+f 1245//1 1291//1 1246//1
+f 1291//1 1292//1 1246//1
+f 1246//1 1292//1 1247//1
+f 1292//1 1293//1 1247//1
+f 1247//1 1293//1 1248//1
+f 1293//1 1294//1 1248//1
+f 1248//1 1294//1 1249//1
+f 1294//1 1295//1 1249//1
+f 1249//1 1295//1 1250//1
+f 1295//1 1296//1 1250//1
+f 1250//1 1296//1 1251//1
+f 1296//1 1297//1 1251//1
+f 1251//1 1297//1 1252//1
+f 1297//1 1298//1 1252//1
+f 1252//1 1298//1 1253//1
+f 1298//1 1299//1 1253//1
+f 1253//1 1299//1 1254//1
+f 1299//1 1300//1 1254//1
+f 1254//1 1300//1 1255//1
+f 1300//1 1301//1 1255//1
+f 1255//1 1301//1 1256//1
+f 1301//1 1302//1 1256//1
+f 1256//1 1302//1 1257//1
+f 1302//1 1303//1 1257//1
+f 1257//1 1303//1 1258//1
+f 1303//1 1304//1 1258//1
+f 1258//1 1304//1 1259//1
+f 1304//1 1305//1 1259//1
+f 1259//1 1305//1 1260//1
+f 1305//1 1306//1 1260//1
+f 1260//1 1306//1 1261//1
+f 1306//1 1307//1 1261//1
+f 1261//1 1307//1 1262//1
+f 1307//1 1308//1 1262//1
+f 1262//1 1308//1 1263//1
+f 1308//1 1309//1 1263//1
+f 1263//1 1309//1 1264//1
+f 1309//1 1310//1 1264//1
+f 1264//1 1310//1 1265//1
+f 1310//1 1311//1 1265//1
+f 1265//1 1311//1 1266//1
+f 1311//1 1312//1 1266//1
+f 1266//1 1312//1 1267//1
+f 1312//1 1313//1 1267//1
+f 1267//1 1313//1 1268//1
+f 1313//1 1314//1 1268//1
+f 1268//1 1314//1 1269//1
+f 1314//1 1315//1 1269//1
+f 1269//1 1315//1 1270//1
+f 1315//1 1316//1 1270//1
+f 1270//1 1316//1 1271//1
+f 1316//1 1317//1 1271//1
+f 1271//1 1317//1 1272//1
+f 1317//1 1318//1 1272//1
+f 1272//1 1318//1 1273//1
+f 1318//1 1319//1 1273//1
+f 1273//1 1319//1 1274//1
+f 1319//1 1320//1 1274//1
+f 1274//1 1320//1 1275//1
+f 1320//1 1321//1 1275//1
+f 1275//1 1321//1 1276//1
+f 1321//1 1322//1 1276//1
+f 1276//1 1322//1 1277//1
+f 1322//1 1323//1 1277//1
+f 1277//1 1323//1 1278//1
+f 1323//1 1324//1 1278//1
+f 1278//1 1324//1 1279//1
+f 1324//1 1325//1 1279//1
+f 1279//1 1325//1 1280//1
+f 1325//1 1326//1 1280//1
+f 1280//1 1326//1 1281//1
+f 1326//1 1327//1 1281//1
+f 1281//1 1327//1 1282//1
+f 1327//1 1328//1 1282//1
+f 1282//1 1328//1 1283//1
+f 1328//1 1329//1 1283//1
+f 1283//1 1329//1 1284//1
+f 1329//1 1330//1 1284//1
+f 1284//1 1330//1 1285//1
+f 1330//1 1331//1 1285//1
+f 1285//1 1331//1 1286//1
+f 1331//1 1332//1 1286//1
+f 1286//1 1332//1 1287//1
+f 1332//1 1333//1 1287//1
+f 1287//1 1333//1 1288//1
+f 1333//1 1334//1 1288//1
+f 1288//1 1334//1 1289//1
+f 1334//1 1335//1 1289//1
+f 1289//1 1335//1 159//1
+f 1335//1 158//1 159//1
+f 251//1 1336//1 1290//1
+f 1336//1 1337//1 1290//1
+f 1290//1 1337//1 1291//1
+f 1337//1 1338//1 1291//1
+f 1291//1 1338//1 1292//1
+f 1338//1 1339//1 1292//1
+f 1292//1 1339//1 1293//1
+f 1339//1 1340//1 1293//1
+f 1293//1 1340//1 1294//1
+f 1340//1 1341//1 1294//1
+f 1294//1 1341//1 1295//1
+f 1341//1 1342//1 1295//1
+f 1295//1 1342//1 1296//1
+f 1342//1 1343//1 1296//1
+f 1296//1 1343//1 1297//1
+f 1343//1 1344//1 1297//1
+f 1297//1 1344//1 1298//1
+f 1344//1 1345//1 1298//1
+f 1298//1 1345//1 1299//1
+f 1345//1 1346//1 1299//1
+f 1299//1 1346//1 1300//1
+f 1346//1 1347//1 1300//1
+f 1300//1 1347//1 1301//1
+f 1347//1 1348//1 1301//1
+f 1301//1 1348//1 1302//1
+f 1348//1 1349//1 1302//1
+f 1302//1 1349//1 1303//1
+f 1349//1 1350//1 1303//1
+f 1303//1 1350//1 1304//1
+f 1350//1 1351//1 1304//1
+f 1304//1 1351//1 1305//1
+f 1351//1 1352//1 1305//1
+f 1305//1 1352//1 1306//1
+f 1352//1 1353//1 1306//1
+f 1306//1 1353//1 1307//1
+f 1353//1 1354//1 1307//1
+f 1307//1 1354//1 1308//1
+f 1354//1 1355//1 1308//1
+f 1308//1 1355//1 1309//1
+f 1355//1 1356//1 1309//1
+f 1309//1 1356//1 1310//1
+f 1356//1 1357//1 1310//1
+f 1310//1 1357//1 1311//1
+f 1357//1 1358//1 1311//1
+f 1311//1 1358//1 1312//1
+f 1358//1 1359//1 1312//1
+f 1312//1 1359//1 1313//1
+f 1359//1 1360//1 1313//1
+f 1313//1 1360//1 1314//1
+f 1360//1 1361//1 1314//1
+f 1314//1 1361//1 1315//1
+f 1361//1 1362//1 1315//1
+f 1315//1 1362//1 1316//1
+f 1362//1 1363//1 1316//1
+f 1316//1 1363//1 1317//1
+f 1363//1 1364//1 1317//1
+f 1317//1 1364//1 1318//1
+f 1364//1 1365//1 1318//1
+f 1318//1 1365//1 1319//1
+f 1365//1 1366//1 1319//1
+f 1319//1 1366//1 1320//1
+f 1366//1 1367//1 1320//1
+f 1320//1 1367//1 1321//1
+f 1367//1 1368//1 1321//1
+f 1321//1 1368//1 1322//1
+f 1368//1 1369//1 1322//1
+f 1322//1 1369//1 1323//1
+f 1369//1 1370//1 1323//1
+f 1323//1 1370//1 1324//1
+f 1370//1 1371//1 1324//1
+f 1324//1 1371//1 1325//1
+f 1371//1 1372//1 1325//1
+f 1325//1 1372//1 1326//1
+f 1372//1 1373//1 1326//1
+f 1326//1 1373//1 1327//1
+f 1373//1 1374//1 1327//1
+f 1327//1 1374//1 1328//1
+f 1374//1 1375//1 1328//1
+f 1328//1 1375//1 1329//1
+f 1375//1 1376//1 1329//1
+f 1329//1 1376//1 1330//1
+f 1376//1 1377//1 1330//1
+f 1330//1 1377//1 1331//1
+f 1377//1 1378//1 1331//1
+f 1331//1 1378//1 1332//1
+f 1378//1 1379//1 1332//1
+f 1332//1 1379//1 1333//1
+f 1379//1 1380//1 1333//1
+f 1333//1 1380//1 1334//1
+f 1380//1 1381//1 1334//1
+f 1334//1 1381//1 1335//1
+f 1381//1 1382//1 1335//1
+f 1335//1 1382//1 158//1
+f 1382//1 157//1 158//1
+f 252//1 1383//1 1336//1
+f 1383//1 1384//1 1336//1
+f 1336//1 1384//1 1337//1
+f 1384//1 1385//1 1337//1
+f 1337//1 1385//1 1338//1
+f 1385//1 1386//1 1338//1
+f 1338//1 1386//1 1339//1
+f 1386//1 1387//1 1339//1
+f 1339//1 1387//1 1340//1
+f 1387//1 1388//1 1340//1
+f 1340//1 1388//1 1341//1
+f 1388//1 1389//1 1341//1
+f 1341//1 1389//1 1342//1
+f 1389//1 1390//1 1342//1
+f 1342//1 1390//1 1343//1
+f 1390//1 1391//1 1343//1
+f 1343//1 1391//1 1344//1
+f 1391//1 1392//1 1344//1
+f 1344//1 1392//1 1345//1
+f 1392//1 1393//1 1345//1
+f 1345//1 1393//1 1346//1
+f 1393//1 1394//1 1346//1
+f 1346//1 1394//1 1347//1
+f 1394//1 1395//1 1347//1
+f 1347//1 1395//1 1348//1
+f 1395//1 1396//1 1348//1
+f 1348//1 1396//1 1349//1
+f 1396//1 1397//1 1349//1
+f 1349//1 1397//1 1350//1
+f 1397//1 1398//1 1350//1
+f 1350//1 1398//1 1351//1
+f 1398//1 1399//1 1351//1
+f 1351//1 1399//1 1352//1
+f 1399//1 1400//1 1352//1
+f 1352//1 1400//1 1353//1
+f 1400//1 1401//1 1353//1
+f 1353//1 1401//1 1354//1
+f 1401//1 1402//1 1354//1
+f 1354//1 1402//1 1355//1
+f 1402//1 1403//1 1355//1
+f 1355//1 1403//1 1356//1
+f 1403//1 1404//1 1356//1
+f 1356//1 1404//1 1357//1
+f 1404//1 1405//1 1357//1
+f 1357//1 1405//1 1358//1
+f 1405//1 1406//1 1358//1
+f 1358//1 1406//1 1359//1
+f 1406//1 1407//1 1359//1
+f 1359//1 1407//1 1360//1
+f 1407//1 1408//1 1360//1
+f 1360//1 1408//1 1361//1
+f 1408//1 1409//1 1361//1
+f 1361//1 1409//1 1362//1
+f 1409//1 1410//1 1362//1
+f 1362//1 1410//1 1363//1
+f 1410//1 1411//1 1363//1
+f 1363//1 1411//1 1364//1
+f 1411//1 1412//1 1364//1
+f 1364//1 1412//1 1365//1
+f 1412//1 1413//1 1365//1
+f 1365//1 1413//1 1366//1
+f 1413//1 1414//1 1366//1
+f 1366//1 1414//1 1367//1
+f 1414//1 1415//1 1367//1
+f 1367//1 1415//1 1368//1
+f 1415//1 1416//1 1368//1
+f 1368//1 1416//1 1369//1
+f 1416//1 1417//1 1369//1
+f 1369//1 1417//1 1370//1
+f 1417//1 1418//1 1370//1
+f 1370//1 1418//1 1371//1
+f 1418//1 1419//1 1371//1
+f 1371//1 1419//1 1372//1
+f 1419//1 1420//1 1372//1
+f 1372//1 1420//1 1373//1
+f 1420//1 1421//1 1373//1
+f 1373//1 1421//1 1374//1
+f 1421//1 1422//1 1374//1
+f 1374//1 1422//1 1375//1
+f 1422//1 1423//1 1375//1
+f 1375//1 1423//1 1376//1
+f 1423//1 1424//1 1376//1
+f 1376//1 1424//1 1377//1
+f 1424//1 1425//1 1377//1
+f 1377//1 1425//1 1378//1
+f 1425//1 1426//1 1378//1
+f 1378//1 1426//1 1379//1
+f 1426//1 1427//1 1379//1
+f 1379//1 1427//1 1380//1
+f 1427//1 1428//1 1380//1
+f 1380//1 1428//1 1381//1
+f 1428//1 1429//1 1381//1
+f 1381//1 1429//1 1382//1
+f 1429//1 1430//1 1382//1
+f 1382//1 1430//1 157//1
+f 1430//1 156//1 157//1
+f 253//1 1431//1 1383//1
+f 1431//1 1432//1 1383//1
+f 1383//1 1432//1 1384//1
+f 1432//1 1433//1 1384//1
+f 1384//1 1433//1 1385//1
+f 1433//1 1434//1 1385//1
+f 1385//1 1434//1 1386//1
+f 1434//1 1435//1 1386//1
+f 1386//1 1435//1 1387//1
+f 1435//1 1436//1 1387//1
+f 1387//1 1436//1 1388//1
+f 1436//1 1437//1 1388//1
+f 1388//1 1437//1 1389//1
+f 1437//1 1438//1 1389//1
+f 1389//1 1438//1 1390//1
+f 1438//1 1439//1 1390//1
+f 1390//1 1439//1 1391//1
+f 1439//1 1440//1 1391//1
+f 1391//1 1440//1 1392//1
+f 1440//1 1441//1 1392//1
+f 1392//1 1441//1 1393//1
+f 1441//1 1442//1 1393//1
+f 1393//1 1442//1 1394//1
+f 1442//1 1443//1 1394//1
+f 1394//1 1443//1 1395//1
+f 1443//1 1444//1 1395//1
+f 1395//1 1444//1 1396//1
+f 1444//1 1445//1 1396//1
+f 1396//1 1445//1 1397//1
+f 1445//1 1446//1 1397//1
+f 1397//1 1446//1 1398//1
+f 1446//1 1447//1 1398//1
+f 1398//1 1447//1 1399//1
+f 1447//1 1448//1 1399//1
+f 1399//1 1448//1 1400//1
+f 1448//1 1449//1 1400//1
+f 1400//1 1449//1 1401//1
+f 1449//1 1450//1 1401//1
+f 1401//1 1450//1 1402//1
+f 1450//1 1451//1 1402//1
+f 1402//1 1451//1 1403//1
+f 1451//1 1452//1 1403//1
+f 1403//1 1452//1 1404//1
+f 1452//1 1453//1 1404//1
+f 1404//1 1453//1 1405//1
+f 1453//1 1454//1 1405//1
+f 1405//1 1454//1 1406//1
+f 1454//1 1455//1 1406//1
+f 1406//1 1455//1 1407//1
+f 1455//1 1456//1 1407//1
+f 1407//1 1456//1 1408//1
+f 1456//1 1457//1 1408//1
+f 1408//1 1457//1 1409//1
+f 1457//1 1458//1 1409//1
+f 1409//1 1458//1 1410//1
+f 1458//1 1459//1 1410//1
+f 1410//1 1459//1 1411//1
+f 1459//1 1460//1 1411//1
+f 1411//1 1460//1 1412//1
+f 1460//1 1461//1 1412//1
+f 1412//1 1461//1 1413//1
+f 1461//1 1462//1 1413//1
+f 1413//1 1462//1 1414//1
+f 1462//1 1463//1 1414//1
+f 1414//1 1463//1 1415//1
+f 1463//1 1464//1 1415//1
+f 1415//1 1464//1 1416//1
+f 1464//1 1465//1 1416//1
+f 1416//1 1465//1 1417//1
+f 1465//1 1466//1 1417//1
+f 1417//1 1466//1 1418//1
+f 1466//1 1467//1 1418//1
+f 1418//1 1467//1 1419//1
+f 1467//1 1468//1 1419//1
+f 1419//1 1468//1 1420//1
+f 1468//1 1469//1 1420//1
+f 1420//1 1469//1 1421//1
+f 1469//1 1470//1 1421//1
+f 1421//1 1470//1 1422//1
+f 1470//1 1471//1 1422//1
+f 1422//1 1471//1 1423//1
+f 1471//1 1472//1 1423//1
+f 1423//1 1472//1 1424//1
+f 1472//1 1473//1 1424//1
+f 1424//1 1473//1 1425//1
+f 1473//1 1474//1 1425//1
+f 1425//1 1474//1 1426//1
+f 1474//1 1475//1 1426//1
+f 1426//1 1475//1 1427//1
+f 1475//1 1476//1 1427//1
+f 1427//1 1476//1 1428//1
+f 1476//1 1477//1 1428//1
+f 1428//1 1477//1 1429//1
+f 1477//1 1478//1 1429//1
+f 1429//1 1478//1 1430//1
+f 1478//1 1479//1 1430//1
+f 1430//1 1479//1 156//1
+f 1479//1 155//1 156//1
+f 254//1 105//1 1431//1
+f 105//1 106//1 1431//1
+f 1431//1 106//1 1432//1
+f 106//1 107//1 1432//1
+f 1432//1 107//1 1433//1
+f 107//1 108//1 1433//1
+f 1433//1 108//1 1434//1
+f 108//1 109//1 1434//1
+f 1434//1 109//1 1435//1
+f 109//1 110//1 1435//1
+f 1435//1 110//1 1436//1
+f 110//1 111//1 1436//1
+f 1436//1 111//1 1437//1
+f 111//1 112//1 1437//1
+f 1437//1 112//1 1438//1
+f 112//1 113//1 1438//1
+f 1438//1 113//1 1439//1
+f 113//1 114//1 1439//1
+f 1439//1 114//1 1440//1
+f 114//1 115//1 1440//1
+f 1440//1 115//1 1441//1
+f 115//1 116//1 1441//1
+f 1441//1 116//1 1442//1
+f 116//1 117//1 1442//1
+f 1442//1 117//1 1443//1
+f 117//1 118//1 1443//1
+f 1443//1 118//1 1444//1
+f 118//1 119//1 1444//1
+f 1444//1 119//1 1445//1
+f 119//1 120//1 1445//1
+f 1445//1 120//1 1446//1
+f 120//1 121//1 1446//1
+f 1446//1 121//1 1447//1
+f 121//1 122//1 1447//1
+f 1447//1 122//1 1448//1
+f 122//1 123//1 1448//1
+f 1448//1 123//1 1449//1
+f 123//1 124//1 1449//1
+f 1449//1 124//1 1450//1
+f 124//1 125//1 1450//1
+f 1450//1 125//1 1451//1
+f 125//1 126//1 1451//1
+f 1451//1 126//1 1452//1
+f 126//1 127//1 1452//1
+f 1452//1 127//1 1453//1
+f 127//1 128//1 1453//1
+f 1453//1 128//1 1454//1
+f 128//1 129//1 1454//1
+f 1454//1 129//1 1455//1
+f 129//1 130//1 1455//1
+f 1455//1 130//1 1456//1
+f 130//1 131//1 1456//1
+f 1456//1 131//1 1457//1
+f 131//1 132//1 1457//1
+f 1457//1 132//1 1458//1
+f 132//1 133//1 1458//1
+f 1458//1 133//1 1459//1
+f 133//1 134//1 1459//1
+f 1459//1 134//1 1460//1
+f 134//1 135//1 1460//1
+f 1460//1 135//1 1461//1
+f 135//1 136//1 1461//1
+f 1461//1 136//1 1462//1
+f 136//1 137//1 1462//1
+f 1462//1 137//1 1463//1
+f 137//1 138//1 1463//1
+f 1463//1 138//1 1464//1
+f 138//1 139//1 1464//1
+f 1464//1 139//1 1465//1
+f 139//1 140//1 1465//1
+f 1465//1 140//1 1466//1
+f 140//1 141//1 1466//1
+f 1466//1 141//1 1467//1
+f 141//1 142//1 1467//1
+f 1467//1 142//1 1468//1
+f 142//1 143//1 1468//1
+f 1468//1 143//1 1469//1
+f 143//1 144//1 1469//1
+f 1469//1 144//1 1470//1
+f 144//1 145//1 1470//1
+f 1470//1 145//1 1471//1
+f 145//1 146//1 1471//1
+f 1471//1 146//1 1472//1
+f 146//1 147//1 1472//1
+f 1472//1 147//1 1473//1
+f 147//1 148//1 1473//1
+f 1473//1 148//1 1474//1
+f 148//1 149//1 1474//1
+f 1474//1 149//1 1475//1
+f 149//1 150//1 1475//1
+f 1475//1 150//1 1476//1
+f 150//1 151//1 1476//1
+f 1476//1 151//1 1477//1
+f 151//1 152//1 1477//1
+f 1477//1 152//1 1478//1
+f 152//1 153//1 1478//1
+f 1478//1 153//1 1479//1
+f 153//1 154//1 1479//1
+f 1479//1 154//1 155//1
+f 154//1 4//1 155//1
+f 55//1 54//1 1//1
+f 56//1 1480//1 55//1
+f 57//1 1481//1 56//1
+f 58//1 1483//1 57//1
+f 59//1 1486//1 58//1
+f 60//1 1490//1 59//1
+f 61//1 1495//1 60//1
+f 62//1 1501//1 61//1
+f 63//1 1508//1 62//1
+f 64//1 1516//1 63//1
+f 65//1 1525//1 64//1
+f 66//1 1535//1 65//1
+f 67//1 1546//1 66//1
+f 68//1 1558//1 67//1
+f 69//1 1571//1 68//1
+f 70//1 1585//1 69//1
+f 71//1 1600//1 70//1
+f 72//1 1616//1 71//1
+f 73//1 1633//1 72//1
+f 74//1 1651//1 73//1
+f 75//1 1670//1 74//1
+f 76//1 1690//1 75//1
+f 77//1 1711//1 76//1
+f 78//1 1733//1 77//1
+f 79//1 1756//1 78//1
+f 80//1 1780//1 79//1
+f 81//1 1805//1 80//1
+f 82//1 1831//1 81//1
+f 83//1 1858//1 82//1
+f 84//1 1886//1 83//1
+f 85//1 1915//1 84//1
+f 86//1 1945//1 85//1
+f 87//1 1976//1 86//1
+f 88//1 2008//1 87//1
+f 89//1 2041//1 88//1
+f 90//1 2075//1 89//1
+f 91//1 2110//1 90//1
+f 92//1 2146//1 91//1
+f 93//1 2183//1 92//1
+f 94//1 2221//1 93//1
+f 95//1 2260//1 94//1
+f 96//1 2300//1 95//1
+f 97//1 2341//1 96//1
+f 98//1 2383//1 97//1
+f 99//1 2426//1 98//1
+f 100//1 2470//1 99//1
+f 101//1 2515//1 100//1
+f 102//1 2561//1 101//1
+f 103//1 2608//1 102//1
+f 104//1 2656//1 103//1
+f 55//1 1480//1 54//1
+f 1480//1 53//1 54//1
+f 56//1 1481//1 1480//1
+f 1481//1 1482//1 1480//1
+f 1480//1 1482//1 53//1
+f 1482//1 52//1 53//1
+f 57//1 1483//1 1481//1
+f 1483//1 1484//1 1481//1
+f 1481//1 1484//1 1482//1
+f 1484//1 1485//1 1482//1
+f 1482//1 1485//1 52//1
+f 1485//1 51//1 52//1
+f 58//1 1486//1 1483//1
+f 1486//1 1487//1 1483//1
+f 1483//1 1487//1 1484//1
+f 1487//1 1488//1 1484//1
+f 1484//1 1488//1 1485//1
+f 1488//1 1489//1 1485//1
+f 1485//1 1489//1 51//1
+f 1489//1 50//1 51//1
+f 59//1 1490//1 1486//1
+f 1490//1 1491//1 1486//1
+f 1486//1 1491//1 1487//1
+f 1491//1 1492//1 1487//1
+f 1487//1 1492//1 1488//1
+f 1492//1 1493//1 1488//1
+f 1488//1 1493//1 1489//1
+f 1493//1 1494//1 1489//1
+f 1489//1 1494//1 50//1
+f 1494//1 49//1 50//1
+f 60//1 1495//1 1490//1
+f 1495//1 1496//1 1490//1
+f 1490//1 1496//1 1491//1
+f 1496//1 1497//1 1491//1
+f 1491//1 1497//1 1492//1
+f 1497//1 1498//1 1492//1
+f 1492//1 1498//1 1493//1
+f 1498//1 1499//1 1493//1
+f 1493//1 1499//1 1494//1
+f 1499//1 1500//1 1494//1
+f 1494//1 1500//1 49//1
+f 1500//1 48//1 49//1
+f 61//1 1501//1 1495//1
+f 1501//1 1502//1 1495//1
+f 1495//1 1502//1 1496//1
+f 1502//1 1503//1 1496//1
+f 1496//1 1503//1 1497//1
+f 1503//1 1504//1 1497//1
+f 1497//1 1504//1 1498//1
+f 1504//1 1505//1 1498//1
+f 1498//1 1505//1 1499//1
+f 1505//1 1506//1 1499//1
+f 1499//1 1506//1 1500//1
+f 1506//1 1507//1 1500//1
+f 1500//1 1507//1 48//1
+f 1507//1 47//1 48//1
+f 62//1 1508//1 1501//1
+f 1508//1 1509//1 1501//1
+f 1501//1 1509//1 1502//1
+f 1509//1 1510//1 1502//1
+f 1502//1 1510//1 1503//1
+f 1510//1 1511//1 1503//1
+f 1503//1 1511//1 1504//1
+f 1511//1 1512//1 1504//1
+f 1504//1 1512//1 1505//1
+f 1512//1 1513//1 1505//1
+f 1505//1 1513//1 1506//1
+f 1513//1 1514//1 1506//1
+f 1506//1 1514//1 1507//1
+f 1514//1 1515//1 1507//1
+f 1507//1 1515//1 47//1
+f 1515//1 46//1 47//1
+f 63//1 1516//1 1508//1
+f 1516//1 1517//1 1508//1
+f 1508//1 1517//1 1509//1
+f 1517//1 1518//1 1509//1
+f 1509//1 1518//1 1510//1
+f 1518//1 1519//1 1510//1
+f 1510//1 1519//1 1511//1
+f 1519//1 1520//1 1511//1
+f 1511//1 1520//1 1512//1
+f 1520//1 1521//1 1512//1
+f 1512//1 1521//1 1513//1
+f 1521//1 1522//1 1513//1
+f 1513//1 1522//1 1514//1
+f 1522//1 1523//1 1514//1
+f 1514//1 1523//1 1515//1
+f 1523//1 1524//1 1515//1
+f 1515//1 1524//1 46//1
+f 1524//1 45//1 46//1
+f 64//1 1525//1 1516//1
+f 1525//1 1526//1 1516//1
+f 1516//1 1526//1 1517//1
+f 1526//1 1527//1 1517//1
+f 1517//1 1527//1 1518//1
+f 1527//1 1528//1 1518//1
+f 1518//1 1528//1 1519//1
+f 1528//1 1529//1 1519//1
+f 1519//1 1529//1 1520//1
+f 1529//1 1530//1 1520//1
+f 1520//1 1530//1 1521//1
+f 1530//1 1531//1 1521//1
+f 1521//1 1531//1 1522//1
+f 1531//1 1532//1 1522//1
+f 1522//1 1532//1 1523//1
+f 1532//1 1533//1 1523//1
+f 1523//1 1533//1 1524//1
+f 1533//1 1534//1 1524//1
+f 1524//1 1534//1 45//1
+f 1534//1 44//1 45//1
+f 65//1 1535//1 1525//1
+f 1535//1 1536//1 1525//1
+f 1525//1 1536//1 1526//1
+f 1536//1 1537//1 1526//1
+f 1526//1 1537//1 1527//1
+f 1537//1 1538//1 1527//1
+f 1527//1 1538//1 1528//1
+f 1538//1 1539//1 1528//1
+f 1528//1 1539//1 1529//1
+f 1539//1 1540//1 1529//1
+f 1529//1 1540//1 1530//1
+f 1540//1 1541//1 1530//1
+f 1530//1 1541//1 1531//1
+f 1541//1 1542//1 1531//1
+f 1531//1 1542//1 1532//1
+f 1542//1 1543//1 1532//1
+f 1532//1 1543//1 1533//1
+f 1543//1 1544//1 1533//1
+f 1533//1 1544//1 1534//1
+f 1544//1 1545//1 1534//1
+f 1534//1 1545//1 44//1
+f 1545//1 43//1 44//1
+f 66//1 1546//1 1535//1
+f 1546//1 1547//1 1535//1
+f 1535//1 1547//1 1536//1
+f 1547//1 1548//1 1536//1
+f 1536//1 1548//1 1537//1
+f 1548//1 1549//1 1537//1
+f 1537//1 1549//1 1538//1
+f 1549//1 1550//1 1538//1
+f 1538//1 1550//1 1539//1
+f 1550//1 1551//1 1539//1
+f 1539//1 1551//1 1540//1
+f 1551//1 1552//1 1540//1
+f 1540//1 1552//1 1541//1
+f 1552//1 1553//1 1541//1
+f 1541//1 1553//1 1542//1
+f 1553//1 1554//1 1542//1
+f 1542//1 1554//1 1543//1
+f 1554//1 1555//1 1543//1
+f 1543//1 1555//1 1544//1
+f 1555//1 1556//1 1544//1
+f 1544//1 1556//1 1545//1
+f 1556//1 1557//1 1545//1
+f 1545//1 1557//1 43//1
+f 1557//1 42//1 43//1
+f 67//1 1558//1 1546//1
+f 1558//1 1559//1 1546//1
+f 1546//1 1559//1 1547//1
+f 1559//1 1560//1 1547//1
+f 1547//1 1560//1 1548//1
+f 1560//1 1561//1 1548//1
+f 1548//1 1561//1 1549//1
+f 1561//1 1562//1 1549//1
+f 1549//1 1562//1 1550//1
+f 1562//1 1563//1 1550//1
+f 1550//1 1563//1 1551//1
+f 1563//1 1564//1 1551//1
+f 1551//1 1564//1 1552//1
+f 1564//1 1565//1 1552//1
+f 1552//1 1565//1 1553//1
+f 1565//1 1566//1 1553//1
+f 1553//1 1566//1 1554//1
+f 1566//1 1567//1 1554//1
+f 1554//1 1567//1 1555//1
+f 1567//1 1568//1 1555//1
+f 1555//1 1568//1 1556//1
+f 1568//1 1569//1 1556//1
+f 1556//1 1569//1 1557//1
+f 1569//1 1570//1 1557//1
+f 1557//1 1570//1 42//1
+f 1570//1 41//1 42//1
+f 68//1 1571//1 1558//1
+f 1571//1 1572//1 1558//1
+f 1558//1 1572//1 1559//1
+f 1572//1 1573//1 1559//1
+f 1559//1 1573//1 1560//1
+f 1573//1 1574//1 1560//1
+f 1560//1 1574//1 1561//1
+f 1574//1 1575//1 1561//1
+f 1561//1 1575//1 1562//1
+f 1575//1 1576//1 1562//1
+f 1562//1 1576//1 1563//1
+f 1576//1 1577//1 1563//1
+f 1563//1 1577//1 1564//1
+f 1577//1 1578//1 1564//1
+f 1564//1 1578//1 1565//1
+f 1578//1 1579//1 1565//1
+f 1565//1 1579//1 1566//1
+f 1579//1 1580//1 1566//1
+f 1566//1 1580//1 1567//1
+f 1580//1 1581//1 1567//1
+f 1567//1 1581//1 1568//1
+f 1581//1 1582//1 1568//1
+f 1568//1 1582//1 1569//1
+f 1582//1 1583//1 1569//1
+f 1569//1 1583//1 1570//1
+f 1583//1 1584//1 1570//1
+f 1570//1 1584//1 41//1
+f 1584//1 40//1 41//1
+f 69//1 1585//1 1571//1
+f 1585//1 1586//1 1571//1
+f 1571//1 1586//1 1572//1
+f 1586//1 1587//1 1572//1
+f 1572//1 1587//1 1573//1
+f 1587//1 1588//1 1573//1
+f 1573//1 1588//1 1574//1
+f 1588//1 1589//1 1574//1
+f 1574//1 1589//1 1575//1
+f 1589//1 1590//1 1575//1
+f 1575//1 1590//1 1576//1
+f 1590//1 1591//1 1576//1
+f 1576//1 1591//1 1577//1
+f 1591//1 1592//1 1577//1
+f 1577//1 1592//1 1578//1
+f 1592//1 1593//1 1578//1
+f 1578//1 1593//1 1579//1
+f 1593//1 1594//1 1579//1
+f 1579//1 1594//1 1580//1
+f 1594//1 1595//1 1580//1
+f 1580//1 1595//1 1581//1
+f 1595//1 1596//1 1581//1
+f 1581//1 1596//1 1582//1
+f 1596//1 1597//1 1582//1
+f 1582//1 1597//1 1583//1
+f 1597//1 1598//1 1583//1
+f 1583//1 1598//1 1584//1
+f 1598//1 1599//1 1584//1
+f 1584//1 1599//1 40//1
+f 1599//1 39//1 40//1
+f 70//1 1600//1 1585//1
+f 1600//1 1601//1 1585//1
+f 1585//1 1601//1 1586//1
+f 1601//1 1602//1 1586//1
+f 1586//1 1602//1 1587//1
+f 1602//1 1603//1 1587//1
+f 1587//1 1603//1 1588//1
+f 1603//1 1604//1 1588//1
+f 1588//1 1604//1 1589//1
+f 1604//1 1605//1 1589//1
+f 1589//1 1605//1 1590//1
+f 1605//1 1606//1 1590//1
+f 1590//1 1606//1 1591//1
+f 1606//1 1607//1 1591//1
+f 1591//1 1607//1 1592//1
+f 1607//1 1608//1 1592//1
+f 1592//1 1608//1 1593//1
+f 1608//1 1609//1 1593//1
+f 1593//1 1609//1 1594//1
+f 1609//1 1610//1 1594//1
+f 1594//1 1610//1 1595//1
+f 1610//1 1611//1 1595//1
+f 1595//1 1611//1 1596//1
+f 1611//1 1612//1 1596//1
+f 1596//1 1612//1 1597//1
+f 1612//1 1613//1 1597//1
+f 1597//1 1613//1 1598//1
+f 1613//1 1614//1 1598//1
+f 1598//1 1614//1 1599//1
+f 1614//1 1615//1 1599//1
+f 1599//1 1615//1 39//1
+f 1615//1 38//1 39//1
+f 71//1 1616//1 1600//1
+f 1616//1 1617//1 1600//1
+f 1600//1 1617//1 1601//1
+f 1617//1 1618//1 1601//1
+f 1601//1 1618//1 1602//1
+f 1618//1 1619//1 1602//1
+f 1602//1 1619//1 1603//1
+f 1619//1 1620//1 1603//1
+f 1603//1 1620//1 1604//1
+f 1620//1 1621//1 1604//1
+f 1604//1 1621//1 1605//1
+f 1621//1 1622//1 1605//1
+f 1605//1 1622//1 1606//1
+f 1622//1 1623//1 1606//1
+f 1606//1 1623//1 1607//1
+f 1623//1 1624//1 1607//1
+f 1607//1 1624//1 1608//1
+f 1624//1 1625//1 1608//1
+f 1608//1 1625//1 1609//1
+f 1625//1 1626//1 1609//1
+f 1609//1 1626//1 1610//1
+f 1626//1 1627//1 1610//1
+f 1610//1 1627//1 1611//1
+f 1627//1 1628//1 1611//1
+f 1611//1 1628//1 1612//1
+f 1628//1 1629//1 1612//1
+f 1612//1 1629//1 1613//1
+f 1629//1 1630//1 1613//1
+f 1613//1 1630//1 1614//1
+f 1630//1 1631//1 1614//1
+f 1614//1 1631//1 1615//1
+f 1631//1 1632//1 1615//1
+f 1615//1 1632//1 38//1
+f 1632//1 37//1 38//1
+f 72//1 1633//1 1616//1
+f 1633//1 1634//1 1616//1
+f 1616//1 1634//1 1617//1
+f 1634//1 1635//1 1617//1
+f 1617//1 1635//1 1618//1
+f 1635//1 1636//1 1618//1
+f 1618//1 1636//1 1619//1
+f 1636//1 1637//1 1619//1
+f 1619//1 1637//1 1620//1
+f 1637//1 1638//1 1620//1
+f 1620//1 1638//1 1621//1
+f 1638//1 1639//1 1621//1
+f 1621//1 1639//1 1622//1
+f 1639//1 1640//1 1622//1
+f 1622//1 1640//1 1623//1
+f 1640//1 1641//1 1623//1
+f 1623//1 1641//1 1624//1
+f 1641//1 1642//1 1624//1
+f 1624//1 1642//1 1625//1
+f 1642//1 1643//1 1625//1
+f 1625//1 1643//1 1626//1
+f 1643//1 1644//1 1626//1
+f 1626//1 1644//1 1627//1
+f 1644//1 1645//1 1627//1
+f 1627//1 1645//1 1628//1
+f 1645//1 1646//1 1628//1
+f 1628//1 1646//1 1629//1
+f 1646//1 1647//1 1629//1
+f 1629//1 1647//1 1630//1
+f 1647//1 1648//1 1630//1
+f 1630//1 1648//1 1631//1
+f 1648//1 1649//1 1631//1
+f 1631//1 1649//1 1632//1
+f 1649//1 1650//1 1632//1
+f 1632//1 1650//1 37//1
+f 1650//1 36//1 37//1
+f 73//1 1651//1 1633//1
+f 1651//1 1652//1 1633//1
+f 1633//1 1652//1 1634//1
+f 1652//1 1653//1 1634//1
+f 1634//1 1653//1 1635//1
+f 1653//1 1654//1 1635//1
+f 1635//1 1654//1 1636//1
+f 1654//1 1655//1 1636//1
+f 1636//1 1655//1 1637//1
+f 1655//1 1656//1 1637//1
+f 1637//1 1656//1 1638//1
+f 1656//1 1657//1 1638//1
+f 1638//1 1657//1 1639//1
+f 1657//1 1658//1 1639//1
+f 1639//1 1658//1 1640//1
+f 1658//1 1659//1 1640//1
+f 1640//1 1659//1 1641//1
+f 1659//1 1660//1 1641//1
+f 1641//1 1660//1 1642//1
+f 1660//1 1661//1 1642//1
+f 1642//1 1661//1 1643//1
+f 1661//1 1662//1 1643//1
+f 1643//1 1662//1 1644//1
+f 1662//1 1663//1 1644//1
+f 1644//1 1663//1 1645//1
+f 1663//1 1664//1 1645//1
+f 1645//1 1664//1 1646//1
+f 1664//1 1665//1 1646//1
+f 1646//1 1665//1 1647//1
+f 1665//1 1666//1 1647//1
+f 1647//1 1666//1 1648//1
+f 1666//1 1667//1 1648//1
+f 1648//1 1667//1 1649//1
+f 1667//1 1668//1 1649//1
+f 1649//1 1668//1 1650//1
+f 1668//1 1669//1 1650//1
+f 1650//1 1669//1 36//1
+f 1669//1 35//1 36//1
+f 74//1 1670//1 1651//1
+f 1670//1 1671//1 1651//1
+f 1651//1 1671//1 1652//1
+f 1671//1 1672//1 1652//1
+f 1652//1 1672//1 1653//1
+f 1672//1 1673//1 1653//1
+f 1653//1 1673//1 1654//1
+f 1673//1 1674//1 1654//1
+f 1654//1 1674//1 1655//1
+f 1674//1 1675//1 1655//1
+f 1655//1 1675//1 1656//1
+f 1675//1 1676//1 1656//1
+f 1656//1 1676//1 1657//1
+f 1676//1 1677//1 1657//1
+f 1657//1 1677//1 1658//1
+f 1677//1 1678//1 1658//1
+f 1658//1 1678//1 1659//1
+f 1678//1 1679//1 1659//1
+f 1659//1 1679//1 1660//1
+f 1679//1 1680//1 1660//1
+f 1660//1 1680//1 1661//1
+f 1680//1 1681//1 1661//1
+f 1661//1 1681//1 1662//1
+f 1681//1 1682//1 1662//1
+f 1662//1 1682//1 1663//1
+f 1682//1 1683//1 1663//1
+f 1663//1 1683//1 1664//1
+f 1683//1 1684//1 1664//1
+f 1664//1 1684//1 1665//1
+f 1684//1 1685//1 1665//1
+f 1665//1 1685//1 1666//1
+f 1685//1 1686//1 1666//1
+f 1666//1 1686//1 1667//1
+f 1686//1 1687//1 1667//1
+f 1667//1 1687//1 1668//1
+f 1687//1 1688//1 1668//1
+f 1668//1 1688//1 1669//1
+f 1688//1 1689//1 1669//1
+f 1669//1 1689//1 35//1
+f 1689//1 34//1 35//1
+f 75//1 1690//1 1670//1
+f 1690//1 1691//1 1670//1
+f 1670//1 1691//1 1671//1
+f 1691//1 1692//1 1671//1
+f 1671//1 1692//1 1672//1
+f 1692//1 1693//1 1672//1
+f 1672//1 1693//1 1673//1
+f 1693//1 1694//1 1673//1
+f 1673//1 1694//1 1674//1
+f 1694//1 1695//1 1674//1
+f 1674//1 1695//1 1675//1
+f 1695//1 1696//1 1675//1
+f 1675//1 1696//1 1676//1
+f 1696//1 1697//1 1676//1
+f 1676//1 1697//1 1677//1
+f 1697//1 1698//1 1677//1
+f 1677//1 1698//1 1678//1
+f 1698//1 1699//1 1678//1
+f 1678//1 1699//1 1679//1
+f 1699//1 1700//1 1679//1
+f 1679//1 1700//1 1680//1
+f 1700//1 1701//1 1680//1
+f 1680//1 1701//1 1681//1
+f 1701//1 1702//1 1681//1
+f 1681//1 1702//1 1682//1
+f 1702//1 1703//1 1682//1
+f 1682//1 1703//1 1683//1
+f 1703//1 1704//1 1683//1
+f 1683//1 1704//1 1684//1
+f 1704//1 1705//1 1684//1
+f 1684//1 1705//1 1685//1
+f 1705//1 1706//1 1685//1
+f 1685//1 1706//1 1686//1
+f 1706//1 1707//1 1686//1
+f 1686//1 1707//1 1687//1
+f 1707//1 1708//1 1687//1
+f 1687//1 1708//1 1688//1
+f 1708//1 1709//1 1688//1
+f 1688//1 1709//1 1689//1
+f 1709//1 1710//1 1689//1
+f 1689//1 1710//1 34//1
+f 1710//1 33//1 34//1
+f 76//1 1711//1 1690//1
+f 1711//1 1712//1 1690//1
+f 1690//1 1712//1 1691//1
+f 1712//1 1713//1 1691//1
+f 1691//1 1713//1 1692//1
+f 1713//1 1714//1 1692//1
+f 1692//1 1714//1 1693//1
+f 1714//1 1715//1 1693//1
+f 1693//1 1715//1 1694//1
+f 1715//1 1716//1 1694//1
+f 1694//1 1716//1 1695//1
+f 1716//1 1717//1 1695//1
+f 1695//1 1717//1 1696//1
+f 1717//1 1718//1 1696//1
+f 1696//1 1718//1 1697//1
+f 1718//1 1719//1 1697//1
+f 1697//1 1719//1 1698//1
+f 1719//1 1720//1 1698//1
+f 1698//1 1720//1 1699//1
+f 1720//1 1721//1 1699//1
+f 1699//1 1721//1 1700//1
+f 1721//1 1722//1 1700//1
+f 1700//1 1722//1 1701//1
+f 1722//1 1723//1 1701//1
+f 1701//1 1723//1 1702//1
+f 1723//1 1724//1 1702//1
+f 1702//1 1724//1 1703//1
+f 1724//1 1725//1 1703//1
+f 1703//1 1725//1 1704//1
+f 1725//1 1726//1 1704//1
+f 1704//1 1726//1 1705//1
+f 1726//1 1727//1 1705//1
+f 1705//1 1727//1 1706//1
+f 1727//1 1728//1 1706//1
+f 1706//1 1728//1 1707//1
+f 1728//1 1729//1 1707//1
+f 1707//1 1729//1 1708//1
+f 1729//1 1730//1 1708//1
+f 1708//1 1730//1 1709//1
+f 1730//1 1731//1 1709//1
+f 1709//1 1731//1 1710//1
+f 1731//1 1732//1 1710//1
+f 1710//1 1732//1 33//1
+f 1732//1 32//1 33//1
+f 77//1 1733//1 1711//1
+f 1733//1 1734//1 1711//1
+f 1711//1 1734//1 1712//1
+f 1734//1 1735//1 1712//1
+f 1712//1 1735//1 1713//1
+f 1735//1 1736//1 1713//1
+f 1713//1 1736//1 1714//1
+f 1736//1 1737//1 1714//1
+f 1714//1 1737//1 1715//1
+f 1737//1 1738//1 1715//1
+f 1715//1 1738//1 1716//1
+f 1738//1 1739//1 1716//1
+f 1716//1 1739//1 1717//1
+f 1739//1 1740//1 1717//1
+f 1717//1 1740//1 1718//1
+f 1740//1 1741//1 1718//1
+f 1718//1 1741//1 1719//1
+f 1741//1 1742//1 1719//1
+f 1719//1 1742//1 1720//1
+f 1742//1 1743//1 1720//1
+f 1720//1 1743//1 1721//1
+f 1743//1 1744//1 1721//1
+f 1721//1 1744//1 1722//1
+f 1744//1 1745//1 1722//1
+f 1722//1 1745//1 1723//1
+f 1745//1 1746//1 1723//1
+f 1723//1 1746//1 1724//1
+f 1746//1 1747//1 1724//1
+f 1724//1 1747//1 1725//1
+f 1747//1 1748//1 1725//1
+f 1725//1 1748//1 1726//1
+f 1748//1 1749//1 1726//1
+f 1726//1 1749//1 1727//1
+f 1749//1 1750//1 1727//1
+f 1727//1 1750//1 1728//1
+f 1750//1 1751//1 1728//1
+f 1728//1 1751//1 1729//1
+f 1751//1 1752//1 1729//1
+f 1729//1 1752//1 1730//1
+f 1752//1 1753//1 1730//1
+f 1730//1 1753//1 1731//1
+f 1753//1 1754//1 1731//1
+f 1731//1 1754//1 1732//1
+f 1754//1 1755//1 1732//1
+f 1732//1 1755//1 32//1
+f 1755//1 31//1 32//1
+f 78//1 1756//1 1733//1
+f 1756//1 1757//1 1733//1
+f 1733//1 1757//1 1734//1
+f 1757//1 1758//1 1734//1
+f 1734//1 1758//1 1735//1
+f 1758//1 1759//1 1735//1
+f 1735//1 1759//1 1736//1
+f 1759//1 1760//1 1736//1
+f 1736//1 1760//1 1737//1
+f 1760//1 1761//1 1737//1
+f 1737//1 1761//1 1738//1
+f 1761//1 1762//1 1738//1
+f 1738//1 1762//1 1739//1
+f 1762//1 1763//1 1739//1
+f 1739//1 1763//1 1740//1
+f 1763//1 1764//1 1740//1
+f 1740//1 1764//1 1741//1
+f 1764//1 1765//1 1741//1
+f 1741//1 1765//1 1742//1
+f 1765//1 1766//1 1742//1
+f 1742//1 1766//1 1743//1
+f 1766//1 1767//1 1743//1
+f 1743//1 1767//1 1744//1
+f 1767//1 1768//1 1744//1
+f 1744//1 1768//1 1745//1
+f 1768//1 1769//1 1745//1
+f 1745//1 1769//1 1746//1
+f 1769//1 1770//1 1746//1
+f 1746//1 1770//1 1747//1
+f 1770//1 1771//1 1747//1
+f 1747//1 1771//1 1748//1
+f 1771//1 1772//1 1748//1
+f 1748//1 1772//1 1749//1
+f 1772//1 1773//1 1749//1
+f 1749//1 1773//1 1750//1
+f 1773//1 1774//1 1750//1
+f 1750//1 1774//1 1751//1
+f 1774//1 1775//1 1751//1
+f 1751//1 1775//1 1752//1
+f 1775//1 1776//1 1752//1
+f 1752//1 1776//1 1753//1
+f 1776//1 1777//1 1753//1
+f 1753//1 1777//1 1754//1
+f 1777//1 1778//1 1754//1
+f 1754//1 1778//1 1755//1
+f 1778//1 1779//1 1755//1
+f 1755//1 1779//1 31//1
+f 1779//1 30//1 31//1
+f 79//1 1780//1 1756//1
+f 1780//1 1781//1 1756//1
+f 1756//1 1781//1 1757//1
+f 1781//1 1782//1 1757//1
+f 1757//1 1782//1 1758//1
+f 1782//1 1783//1 1758//1
+f 1758//1 1783//1 1759//1
+f 1783//1 1784//1 1759//1
+f 1759//1 1784//1 1760//1
+f 1784//1 1785//1 1760//1
+f 1760//1 1785//1 1761//1
+f 1785//1 1786//1 1761//1
+f 1761//1 1786//1 1762//1
+f 1786//1 1787//1 1762//1
+f 1762//1 1787//1 1763//1
+f 1787//1 1788//1 1763//1
+f 1763//1 1788//1 1764//1
+f 1788//1 1789//1 1764//1
+f 1764//1 1789//1 1765//1
+f 1789//1 1790//1 1765//1
+f 1765//1 1790//1 1766//1
+f 1790//1 1791//1 1766//1
+f 1766//1 1791//1 1767//1
+f 1791//1 1792//1 1767//1
+f 1767//1 1792//1 1768//1
+f 1792//1 1793//1 1768//1
+f 1768//1 1793//1 1769//1
+f 1793//1 1794//1 1769//1
+f 1769//1 1794//1 1770//1
+f 1794//1 1795//1 1770//1
+f 1770//1 1795//1 1771//1
+f 1795//1 1796//1 1771//1
+f 1771//1 1796//1 1772//1
+f 1796//1 1797//1 1772//1
+f 1772//1 1797//1 1773//1
+f 1797//1 1798//1 1773//1
+f 1773//1 1798//1 1774//1
+f 1798//1 1799//1 1774//1
+f 1774//1 1799//1 1775//1
+f 1799//1 1800//1 1775//1
+f 1775//1 1800//1 1776//1
+f 1800//1 1801//1 1776//1
+f 1776//1 1801//1 1777//1
+f 1801//1 1802//1 1777//1
+f 1777//1 1802//1 1778//1
+f 1802//1 1803//1 1778//1
+f 1778//1 1803//1 1779//1
+f 1803//1 1804//1 1779//1
+f 1779//1 1804//1 30//1
+f 1804//1 29//1 30//1
+f 80//1 1805//1 1780//1
+f 1805//1 1806//1 1780//1
+f 1780//1 1806//1 1781//1
+f 1806//1 1807//1 1781//1
+f 1781//1 1807//1 1782//1
+f 1807//1 1808//1 1782//1
+f 1782//1 1808//1 1783//1
+f 1808//1 1809//1 1783//1
+f 1783//1 1809//1 1784//1
+f 1809//1 1810//1 1784//1
+f 1784//1 1810//1 1785//1
+f 1810//1 1811//1 1785//1
+f 1785//1 1811//1 1786//1
+f 1811//1 1812//1 1786//1
+f 1786//1 1812//1 1787//1
+f 1812//1 1813//1 1787//1
+f 1787//1 1813//1 1788//1
+f 1813//1 1814//1 1788//1
+f 1788//1 1814//1 1789//1
+f 1814//1 1815//1 1789//1
+f 1789//1 1815//1 1790//1
+f 1815//1 1816//1 1790//1
+f 1790//1 1816//1 1791//1
+f 1816//1 1817//1 1791//1
+f 1791//1 1817//1 1792//1
+f 1817//1 1818//1 1792//1
+f 1792//1 1818//1 1793//1
+f 1818//1 1819//1 1793//1
+f 1793//1 1819//1 1794//1
+f 1819//1 1820//1 1794//1
+f 1794//1 1820//1 1795//1
+f 1820//1 1821//1 1795//1
+f 1795//1 1821//1 1796//1
+f 1821//1 1822//1 1796//1
+f 1796//1 1822//1 1797//1
+f 1822//1 1823//1 1797//1
+f 1797//1 1823//1 1798//1
+f 1823//1 1824//1 1798//1
+f 1798//1 1824//1 1799//1
+f 1824//1 1825//1 1799//1
+f 1799//1 1825//1 1800//1
+f 1825//1 1826//1 1800//1
+f 1800//1 1826//1 1801//1
+f 1826//1 1827//1 1801//1
+f 1801//1 1827//1 1802//1
+f 1827//1 1828//1 1802//1
+f 1802//1 1828//1 1803//1
+f 1828//1 1829//1 1803//1
+f 1803//1 1829//1 1804//1
+f 1829//1 1830//1 1804//1
+f 1804//1 1830//1 29//1
+f 1830//1 28//1 29//1
+f 81//1 1831//1 1805//1
+f 1831//1 1832//1 1805//1
+f 1805//1 1832//1 1806//1
+f 1832//1 1833//1 1806//1
+f 1806//1 1833//1 1807//1
+f 1833//1 1834//1 1807//1
+f 1807//1 1834//1 1808//1
+f 1834//1 1835//1 1808//1
+f 1808//1 1835//1 1809//1
+f 1835//1 1836//1 1809//1
+f 1809//1 1836//1 1810//1
+f 1836//1 1837//1 1810//1
+f 1810//1 1837//1 1811//1
+f 1837//1 1838//1 1811//1
+f 1811//1 1838//1 1812//1
+f 1838//1 1839//1 1812//1
+f 1812//1 1839//1 1813//1
+f 1839//1 1840//1 1813//1
+f 1813//1 1840//1 1814//1
+f 1840//1 1841//1 1814//1
+f 1814//1 1841//1 1815//1
+f 1841//1 1842//1 1815//1
+f 1815//1 1842//1 1816//1
+f 1842//1 1843//1 1816//1
+f 1816//1 1843//1 1817//1
+f 1843//1 1844//1 1817//1
+f 1817//1 1844//1 1818//1
+f 1844//1 1845//1 1818//1
+f 1818//1 1845//1 1819//1
+f 1845//1 1846//1 1819//1
+f 1819//1 1846//1 1820//1
+f 1846//1 1847//1 1820//1
+f 1820//1 1847//1 1821//1
+f 1847//1 1848//1 1821//1
+f 1821//1 1848//1 1822//1
+f 1848//1 1849//1 1822//1
+f 1822//1 1849//1 1823//1
+f 1849//1 1850//1 1823//1
+f 1823//1 1850//1 1824//1
+f 1850//1 1851//1 1824//1
+f 1824//1 1851//1 1825//1
+f 1851//1 1852//1 1825//1
+f 1825//1 1852//1 1826//1
+f 1852//1 1853//1 1826//1
+f 1826//1 1853//1 1827//1
+f 1853//1 1854//1 1827//1
+f 1827//1 1854//1 1828//1
+f 1854//1 1855//1 1828//1
+f 1828//1 1855//1 1829//1
+f 1855//1 1856//1 1829//1
+f 1829//1 1856//1 1830//1
+f 1856//1 1857//1 1830//1
+f 1830//1 1857//1 28//1
+f 1857//1 27//1 28//1
+f 82//1 1858//1 1831//1
+f 1858//1 1859//1 1831//1
+f 1831//1 1859//1 1832//1
+f 1859//1 1860//1 1832//1
+f 1832//1 1860//1 1833//1
+f 1860//1 1861//1 1833//1
+f 1833//1 1861//1 1834//1
+f 1861//1 1862//1 1834//1
+f 1834//1 1862//1 1835//1
+f 1862//1 1863//1 1835//1
+f 1835//1 1863//1 1836//1
+f 1863//1 1864//1 1836//1
+f 1836//1 1864//1 1837//1
+f 1864//1 1865//1 1837//1
+f 1837//1 1865//1 1838//1
+f 1865//1 1866//1 1838//1
+f 1838//1 1866//1 1839//1
+f 1866//1 1867//1 1839//1
+f 1839//1 1867//1 1840//1
+f 1867//1 1868//1 1840//1
+f 1840//1 1868//1 1841//1
+f 1868//1 1869//1 1841//1
+f 1841//1 1869//1 1842//1
+f 1869//1 1870//1 1842//1
+f 1842//1 1870//1 1843//1
+f 1870//1 1871//1 1843//1
+f 1843//1 1871//1 1844//1
+f 1871//1 1872//1 1844//1
+f 1844//1 1872//1 1845//1
+f 1872//1 1873//1 1845//1
+f 1845//1 1873//1 1846//1
+f 1873//1 1874//1 1846//1
+f 1846//1 1874//1 1847//1
+f 1874//1 1875//1 1847//1
+f 1847//1 1875//1 1848//1
+f 1875//1 1876//1 1848//1
+f 1848//1 1876//1 1849//1
+f 1876//1 1877//1 1849//1
+f 1849//1 1877//1 1850//1
+f 1877//1 1878//1 1850//1
+f 1850//1 1878//1 1851//1
+f 1878//1 1879//1 1851//1
+f 1851//1 1879//1 1852//1
+f 1879//1 1880//1 1852//1
+f 1852//1 1880//1 1853//1
+f 1880//1 1881//1 1853//1
+f 1853//1 1881//1 1854//1
+f 1881//1 1882//1 1854//1
+f 1854//1 1882//1 1855//1
+f 1882//1 1883//1 1855//1
+f 1855//1 1883//1 1856//1
+f 1883//1 1884//1 1856//1
+f 1856//1 1884//1 1857//1
+f 1884//1 1885//1 1857//1
+f 1857//1 1885//1 27//1
+f 1885//1 26//1 27//1
+f 83//1 1886//1 1858//1
+f 1886//1 1887//1 1858//1
+f 1858//1 1887//1 1859//1
+f 1887//1 1888//1 1859//1
+f 1859//1 1888//1 1860//1
+f 1888//1 1889//1 1860//1
+f 1860//1 1889//1 1861//1
+f 1889//1 1890//1 1861//1
+f 1861//1 1890//1 1862//1
+f 1890//1 1891//1 1862//1
+f 1862//1 1891//1 1863//1
+f 1891//1 1892//1 1863//1
+f 1863//1 1892//1 1864//1
+f 1892//1 1893//1 1864//1
+f 1864//1 1893//1 1865//1
+f 1893//1 1894//1 1865//1
+f 1865//1 1894//1 1866//1
+f 1894//1 1895//1 1866//1
+f 1866//1 1895//1 1867//1
+f 1895//1 1896//1 1867//1
+f 1867//1 1896//1 1868//1
+f 1896//1 1897//1 1868//1
+f 1868//1 1897//1 1869//1
+f 1897//1 1898//1 1869//1
+f 1869//1 1898//1 1870//1
+f 1898//1 1899//1 1870//1
+f 1870//1 1899//1 1871//1
+f 1899//1 1900//1 1871//1
+f 1871//1 1900//1 1872//1
+f 1900//1 1901//1 1872//1
+f 1872//1 1901//1 1873//1
+f 1901//1 1902//1 1873//1
+f 1873//1 1902//1 1874//1
+f 1902//1 1903//1 1874//1
+f 1874//1 1903//1 1875//1
+f 1903//1 1904//1 1875//1
+f 1875//1 1904//1 1876//1
+f 1904//1 1905//1 1876//1
+f 1876//1 1905//1 1877//1
+f 1905//1 1906//1 1877//1
+f 1877//1 1906//1 1878//1
+f 1906//1 1907//1 1878//1
+f 1878//1 1907//1 1879//1
+f 1907//1 1908//1 1879//1
+f 1879//1 1908//1 1880//1
+f 1908//1 1909//1 1880//1
+f 1880//1 1909//1 1881//1
+f 1909//1 1910//1 1881//1
+f 1881//1 1910//1 1882//1
+f 1910//1 1911//1 1882//1
+f 1882//1 1911//1 1883//1
+f 1911//1 1912//1 1883//1
+f 1883//1 1912//1 1884//1
+f 1912//1 1913//1 1884//1
+f 1884//1 1913//1 1885//1
+f 1913//1 1914//1 1885//1
+f 1885//1 1914//1 26//1
+f 1914//1 25//1 26//1
+f 84//1 1915//1 1886//1
+f 1915//1 1916//1 1886//1
+f 1886//1 1916//1 1887//1
+f 1916//1 1917//1 1887//1
+f 1887//1 1917//1 1888//1
+f 1917//1 1918//1 1888//1
+f 1888//1 1918//1 1889//1
+f 1918//1 1919//1 1889//1
+f 1889//1 1919//1 1890//1
+f 1919//1 1920//1 1890//1
+f 1890//1 1920//1 1891//1
+f 1920//1 1921//1 1891//1
+f 1891//1 1921//1 1892//1
+f 1921//1 1922//1 1892//1
+f 1892//1 1922//1 1893//1
+f 1922//1 1923//1 1893//1
+f 1893//1 1923//1 1894//1
+f 1923//1 1924//1 1894//1
+f 1894//1 1924//1 1895//1
+f 1924//1 1925//1 1895//1
+f 1895//1 1925//1 1896//1
+f 1925//1 1926//1 1896//1
+f 1896//1 1926//1 1897//1
+f 1926//1 1927//1 1897//1
+f 1897//1 1927//1 1898//1
+f 1927//1 1928//1 1898//1
+f 1898//1 1928//1 1899//1
+f 1928//1 1929//1 1899//1
+f 1899//1 1929//1 1900//1
+f 1929//1 1930//1 1900//1
+f 1900//1 1930//1 1901//1
+f 1930//1 1931//1 1901//1
+f 1901//1 1931//1 1902//1
+f 1931//1 1932//1 1902//1
+f 1902//1 1932//1 1903//1
+f 1932//1 1933//1 1903//1
+f 1903//1 1933//1 1904//1
+f 1933//1 1934//1 1904//1
+f 1904//1 1934//1 1905//1
+f 1934//1 1935//1 1905//1
+f 1905//1 1935//1 1906//1
+f 1935//1 1936//1 1906//1
+f 1906//1 1936//1 1907//1
+f 1936//1 1937//1 1907//1
+f 1907//1 1937//1 1908//1
+f 1937//1 1938//1 1908//1
+f 1908//1 1938//1 1909//1
+f 1938//1 1939//1 1909//1
+f 1909//1 1939//1 1910//1
+f 1939//1 1940//1 1910//1
+f 1910//1 1940//1 1911//1
+f 1940//1 1941//1 1911//1
+f 1911//1 1941//1 1912//1
+f 1941//1 1942//1 1912//1
+f 1912//1 1942//1 1913//1
+f 1942//1 1943//1 1913//1
+f 1913//1 1943//1 1914//1
+f 1943//1 1944//1 1914//1
+f 1914//1 1944//1 25//1
+f 1944//1 24//1 25//1
+f 85//1 1945//1 1915//1
+f 1945//1 1946//1 1915//1
+f 1915//1 1946//1 1916//1
+f 1946//1 1947//1 1916//1
+f 1916//1 1947//1 1917//1
+f 1947//1 1948//1 1917//1
+f 1917//1 1948//1 1918//1
+f 1948//1 1949//1 1918//1
+f 1918//1 1949//1 1919//1
+f 1949//1 1950//1 1919//1
+f 1919//1 1950//1 1920//1
+f 1950//1 1951//1 1920//1
+f 1920//1 1951//1 1921//1
+f 1951//1 1952//1 1921//1
+f 1921//1 1952//1 1922//1
+f 1952//1 1953//1 1922//1
+f 1922//1 1953//1 1923//1
+f 1953//1 1954//1 1923//1
+f 1923//1 1954//1 1924//1
+f 1954//1 1955//1 1924//1
+f 1924//1 1955//1 1925//1
+f 1955//1 1956//1 1925//1
+f 1925//1 1956//1 1926//1
+f 1956//1 1957//1 1926//1
+f 1926//1 1957//1 1927//1
+f 1957//1 1958//1 1927//1
+f 1927//1 1958//1 1928//1
+f 1958//1 1959//1 1928//1
+f 1928//1 1959//1 1929//1
+f 1959//1 1960//1 1929//1
+f 1929//1 1960//1 1930//1
+f 1960//1 1961//1 1930//1
+f 1930//1 1961//1 1931//1
+f 1961//1 1962//1 1931//1
+f 1931//1 1962//1 1932//1
+f 1962//1 1963//1 1932//1
+f 1932//1 1963//1 1933//1
+f 1963//1 1964//1 1933//1
+f 1933//1 1964//1 1934//1
+f 1964//1 1965//1 1934//1
+f 1934//1 1965//1 1935//1
+f 1965//1 1966//1 1935//1
+f 1935//1 1966//1 1936//1
+f 1966//1 1967//1 1936//1
+f 1936//1 1967//1 1937//1
+f 1967//1 1968//1 1937//1
+f 1937//1 1968//1 1938//1
+f 1968//1 1969//1 1938//1
+f 1938//1 1969//1 1939//1
+f 1969//1 1970//1 1939//1
+f 1939//1 1970//1 1940//1
+f 1970//1 1971//1 1940//1
+f 1940//1 1971//1 1941//1
+f 1971//1 1972//1 1941//1
+f 1941//1 1972//1 1942//1
+f 1972//1 1973//1 1942//1
+f 1942//1 1973//1 1943//1
+f 1973//1 1974//1 1943//1
+f 1943//1 1974//1 1944//1
+f 1974//1 1975//1 1944//1
+f 1944//1 1975//1 24//1
+f 1975//1 23//1 24//1
+f 86//1 1976//1 1945//1
+f 1976//1 1977//1 1945//1
+f 1945//1 1977//1 1946//1
+f 1977//1 1978//1 1946//1
+f 1946//1 1978//1 1947//1
+f 1978//1 1979//1 1947//1
+f 1947//1 1979//1 1948//1
+f 1979//1 1980//1 1948//1
+f 1948//1 1980//1 1949//1
+f 1980//1 1981//1 1949//1
+f 1949//1 1981//1 1950//1
+f 1981//1 1982//1 1950//1
+f 1950//1 1982//1 1951//1
+f 1982//1 1983//1 1951//1
+f 1951//1 1983//1 1952//1
+f 1983//1 1984//1 1952//1
+f 1952//1 1984//1 1953//1
+f 1984//1 1985//1 1953//1
+f 1953//1 1985//1 1954//1
+f 1985//1 1986//1 1954//1
+f 1954//1 1986//1 1955//1
+f 1986//1 1987//1 1955//1
+f 1955//1 1987//1 1956//1
+f 1987//1 1988//1 1956//1
+f 1956//1 1988//1 1957//1
+f 1988//1 1989//1 1957//1
+f 1957//1 1989//1 1958//1
+f 1989//1 1990//1 1958//1
+f 1958//1 1990//1 1959//1
+f 1990//1 1991//1 1959//1
+f 1959//1 1991//1 1960//1
+f 1991//1 1992//1 1960//1
+f 1960//1 1992//1 1961//1
+f 1992//1 1993//1 1961//1
+f 1961//1 1993//1 1962//1
+f 1993//1 1994//1 1962//1
+f 1962//1 1994//1 1963//1
+f 1994//1 1995//1 1963//1
+f 1963//1 1995//1 1964//1
+f 1995//1 1996//1 1964//1
+f 1964//1 1996//1 1965//1
+f 1996//1 1997//1 1965//1
+f 1965//1 1997//1 1966//1
+f 1997//1 1998//1 1966//1
+f 1966//1 1998//1 1967//1
+f 1998//1 1999//1 1967//1
+f 1967//1 1999//1 1968//1
+f 1999//1 2000//1 1968//1
+f 1968//1 2000//1 1969//1
+f 2000//1 2001//1 1969//1
+f 1969//1 2001//1 1970//1
+f 2001//1 2002//1 1970//1
+f 1970//1 2002//1 1971//1
+f 2002//1 2003//1 1971//1
+f 1971//1 2003//1 1972//1
+f 2003//1 2004//1 1972//1
+f 1972//1 2004//1 1973//1
+f 2004//1 2005//1 1973//1
+f 1973//1 2005//1 1974//1
+f 2005//1 2006//1 1974//1
+f 1974//1 2006//1 1975//1
+f 2006//1 2007//1 1975//1
+f 1975//1 2007//1 23//1
+f 2007//1 22//1 23//1
+f 87//1 2008//1 1976//1
+f 2008//1 2009//1 1976//1
+f 1976//1 2009//1 1977//1
+f 2009//1 2010//1 1977//1
+f 1977//1 2010//1 1978//1
+f 2010//1 2011//1 1978//1
+f 1978//1 2011//1 1979//1
+f 2011//1 2012//1 1979//1
+f 1979//1 2012//1 1980//1
+f 2012//1 2013//1 1980//1
+f 1980//1 2013//1 1981//1
+f 2013//1 2014//1 1981//1
+f 1981//1 2014//1 1982//1
+f 2014//1 2015//1 1982//1
+f 1982//1 2015//1 1983//1
+f 2015//1 2016//1 1983//1
+f 1983//1 2016//1 1984//1
+f 2016//1 2017//1 1984//1
+f 1984//1 2017//1 1985//1
+f 2017//1 2018//1 1985//1
+f 1985//1 2018//1 1986//1
+f 2018//1 2019//1 1986//1
+f 1986//1 2019//1 1987//1
+f 2019//1 2020//1 1987//1
+f 1987//1 2020//1 1988//1
+f 2020//1 2021//1 1988//1
+f 1988//1 2021//1 1989//1
+f 2021//1 2022//1 1989//1
+f 1989//1 2022//1 1990//1
+f 2022//1 2023//1 1990//1
+f 1990//1 2023//1 1991//1
+f 2023//1 2024//1 1991//1
+f 1991//1 2024//1 1992//1
+f 2024//1 2025//1 1992//1
+f 1992//1 2025//1 1993//1
+f 2025//1 2026//1 1993//1
+f 1993//1 2026//1 1994//1
+f 2026//1 2027//1 1994//1
+f 1994//1 2027//1 1995//1
+f 2027//1 2028//1 1995//1
+f 1995//1 2028//1 1996//1
+f 2028//1 2029//1 1996//1
+f 1996//1 2029//1 1997//1
+f 2029//1 2030//1 1997//1
+f 1997//1 2030//1 1998//1
+f 2030//1 2031//1 1998//1
+f 1998//1 2031//1 1999//1
+f 2031//1 2032//1 1999//1
+f 1999//1 2032//1 2000//1
+f 2032//1 2033//1 2000//1
+f 2000//1 2033//1 2001//1
+f 2033//1 2034//1 2001//1
+f 2001//1 2034//1 2002//1
+f 2034//1 2035//1 2002//1
+f 2002//1 2035//1 2003//1
+f 2035//1 2036//1 2003//1
+f 2003//1 2036//1 2004//1
+f 2036//1 2037//1 2004//1
+f 2004//1 2037//1 2005//1
+f 2037//1 2038//1 2005//1
+f 2005//1 2038//1 2006//1
+f 2038//1 2039//1 2006//1
+f 2006//1 2039//1 2007//1
+f 2039//1 2040//1 2007//1
+f 2007//1 2040//1 22//1
+f 2040//1 21//1 22//1
+f 88//1 2041//1 2008//1
+f 2041//1 2042//1 2008//1
+f 2008//1 2042//1 2009//1
+f 2042//1 2043//1 2009//1
+f 2009//1 2043//1 2010//1
+f 2043//1 2044//1 2010//1
+f 2010//1 2044//1 2011//1
+f 2044//1 2045//1 2011//1
+f 2011//1 2045//1 2012//1
+f 2045//1 2046//1 2012//1
+f 2012//1 2046//1 2013//1
+f 2046//1 2047//1 2013//1
+f 2013//1 2047//1 2014//1
+f 2047//1 2048//1 2014//1
+f 2014//1 2048//1 2015//1
+f 2048//1 2049//1 2015//1
+f 2015//1 2049//1 2016//1
+f 2049//1 2050//1 2016//1
+f 2016//1 2050//1 2017//1
+f 2050//1 2051//1 2017//1
+f 2017//1 2051//1 2018//1
+f 2051//1 2052//1 2018//1
+f 2018//1 2052//1 2019//1
+f 2052//1 2053//1 2019//1
+f 2019//1 2053//1 2020//1
+f 2053//1 2054//1 2020//1
+f 2020//1 2054//1 2021//1
+f 2054//1 2055//1 2021//1
+f 2021//1 2055//1 2022//1
+f 2055//1 2056//1 2022//1
+f 2022//1 2056//1 2023//1
+f 2056//1 2057//1 2023//1
+f 2023//1 2057//1 2024//1
+f 2057//1 2058//1 2024//1
+f 2024//1 2058//1 2025//1
+f 2058//1 2059//1 2025//1
+f 2025//1 2059//1 2026//1
+f 2059//1 2060//1 2026//1
+f 2026//1 2060//1 2027//1
+f 2060//1 2061//1 2027//1
+f 2027//1 2061//1 2028//1
+f 2061//1 2062//1 2028//1
+f 2028//1 2062//1 2029//1
+f 2062//1 2063//1 2029//1
+f 2029//1 2063//1 2030//1
+f 2063//1 2064//1 2030//1
+f 2030//1 2064//1 2031//1
+f 2064//1 2065//1 2031//1
+f 2031//1 2065//1 2032//1
+f 2065//1 2066//1 2032//1
+f 2032//1 2066//1 2033//1
+f 2066//1 2067//1 2033//1
+f 2033//1 2067//1 2034//1
+f 2067//1 2068//1 2034//1
+f 2034//1 2068//1 2035//1
+f 2068//1 2069//1 2035//1
+f 2035//1 2069//1 2036//1
+f 2069//1 2070//1 2036//1
+f 2036//1 2070//1 2037//1
+f 2070//1 2071//1 2037//1
+f 2037//1 2071//1 2038//1
+f 2071//1 2072//1 2038//1
+f 2038//1 2072//1 2039//1
+f 2072//1 2073//1 2039//1
+f 2039//1 2073//1 2040//1
+f 2073//1 2074//1 2040//1
+f 2040//1 2074//1 21//1
+f 2074//1 20//1 21//1
+f 89//1 2075//1 2041//1
+f 2075//1 2076//1 2041//1
+f 2041//1 2076//1 2042//1
+f 2076//1 2077//1 2042//1
+f 2042//1 2077//1 2043//1
+f 2077//1 2078//1 2043//1
+f 2043//1 2078//1 2044//1
+f 2078//1 2079//1 2044//1
+f 2044//1 2079//1 2045//1
+f 2079//1 2080//1 2045//1
+f 2045//1 2080//1 2046//1
+f 2080//1 2081//1 2046//1
+f 2046//1 2081//1 2047//1
+f 2081//1 2082//1 2047//1
+f 2047//1 2082//1 2048//1
+f 2082//1 2083//1 2048//1
+f 2048//1 2083//1 2049//1
+f 2083//1 2084//1 2049//1
+f 2049//1 2084//1 2050//1
+f 2084//1 2085//1 2050//1
+f 2050//1 2085//1 2051//1
+f 2085//1 2086//1 2051//1
+f 2051//1 2086//1 2052//1
+f 2086//1 2087//1 2052//1
+f 2052//1 2087//1 2053//1
+f 2087//1 2088//1 2053//1
+f 2053//1 2088//1 2054//1
+f 2088//1 2089//1 2054//1
+f 2054//1 2089//1 2055//1
+f 2089//1 2090//1 2055//1
+f 2055//1 2090//1 2056//1
+f 2090//1 2091//1 2056//1
+f 2056//1 2091//1 2057//1
+f 2091//1 2092//1 2057//1
+f 2057//1 2092//1 2058//1
+f 2092//1 2093//1 2058//1
+f 2058//1 2093//1 2059//1
+f 2093//1 2094//1 2059//1
+f 2059//1 2094//1 2060//1
+f 2094//1 2095//1 2060//1
+f 2060//1 2095//1 2061//1
+f 2095//1 2096//1 2061//1
+f 2061//1 2096//1 2062//1
+f 2096//1 2097//1 2062//1
+f 2062//1 2097//1 2063//1
+f 2097//1 2098//1 2063//1
+f 2063//1 2098//1 2064//1
+f 2098//1 2099//1 2064//1
+f 2064//1 2099//1 2065//1
+f 2099//1 2100//1 2065//1
+f 2065//1 2100//1 2066//1
+f 2100//1 2101//1 2066//1
+f 2066//1 2101//1 2067//1
+f 2101//1 2102//1 2067//1
+f 2067//1 2102//1 2068//1
+f 2102//1 2103//1 2068//1
+f 2068//1 2103//1 2069//1
+f 2103//1 2104//1 2069//1
+f 2069//1 2104//1 2070//1
+f 2104//1 2105//1 2070//1
+f 2070//1 2105//1 2071//1
+f 2105//1 2106//1 2071//1
+f 2071//1 2106//1 2072//1
+f 2106//1 2107//1 2072//1
+f 2072//1 2107//1 2073//1
+f 2107//1 2108//1 2073//1
+f 2073//1 2108//1 2074//1
+f 2108//1 2109//1 2074//1
+f 2074//1 2109//1 20//1
+f 2109//1 19//1 20//1
+f 90//1 2110//1 2075//1
+f 2110//1 2111//1 2075//1
+f 2075//1 2111//1 2076//1
+f 2111//1 2112//1 2076//1
+f 2076//1 2112//1 2077//1
+f 2112//1 2113//1 2077//1
+f 2077//1 2113//1 2078//1
+f 2113//1 2114//1 2078//1
+f 2078//1 2114//1 2079//1
+f 2114//1 2115//1 2079//1
+f 2079//1 2115//1 2080//1
+f 2115//1 2116//1 2080//1
+f 2080//1 2116//1 2081//1
+f 2116//1 2117//1 2081//1
+f 2081//1 2117//1 2082//1
+f 2117//1 2118//1 2082//1
+f 2082//1 2118//1 2083//1
+f 2118//1 2119//1 2083//1
+f 2083//1 2119//1 2084//1
+f 2119//1 2120//1 2084//1
+f 2084//1 2120//1 2085//1
+f 2120//1 2121//1 2085//1
+f 2085//1 2121//1 2086//1
+f 2121//1 2122//1 2086//1
+f 2086//1 2122//1 2087//1
+f 2122//1 2123//1 2087//1
+f 2087//1 2123//1 2088//1
+f 2123//1 2124//1 2088//1
+f 2088//1 2124//1 2089//1
+f 2124//1 2125//1 2089//1
+f 2089//1 2125//1 2090//1
+f 2125//1 2126//1 2090//1
+f 2090//1 2126//1 2091//1
+f 2126//1 2127//1 2091//1
+f 2091//1 2127//1 2092//1
+f 2127//1 2128//1 2092//1
+f 2092//1 2128//1 2093//1
+f 2128//1 2129//1 2093//1
+f 2093//1 2129//1 2094//1
+f 2129//1 2130//1 2094//1
+f 2094//1 2130//1 2095//1
+f 2130//1 2131//1 2095//1
+f 2095//1 2131//1 2096//1
+f 2131//1 2132//1 2096//1
+f 2096//1 2132//1 2097//1
+f 2132//1 2133//1 2097//1
+f 2097//1 2133//1 2098//1
+f 2133//1 2134//1 2098//1
+f 2098//1 2134//1 2099//1
+f 2134//1 2135//1 2099//1
+f 2099//1 2135//1 2100//1
+f 2135//1 2136//1 2100//1
+f 2100//1 2136//1 2101//1
+f 2136//1 2137//1 2101//1
+f 2101//1 2137//1 2102//1
+f 2137//1 2138//1 2102//1
+f 2102//1 2138//1 2103//1
+f 2138//1 2139//1 2103//1
+f 2103//1 2139//1 2104//1
+f 2139//1 2140//1 2104//1
+f 2104//1 2140//1 2105//1
+f 2140//1 2141//1 2105//1
+f 2105//1 2141//1 2106//1
+f 2141//1 2142//1 2106//1
+f 2106//1 2142//1 2107//1
+f 2142//1 2143//1 2107//1
+f 2107//1 2143//1 2108//1
+f 2143//1 2144//1 2108//1
+f 2108//1 2144//1 2109//1
+f 2144//1 2145//1 2109//1
+f 2109//1 2145//1 19//1
+f 2145//1 18//1 19//1
+f 91//1 2146//1 2110//1
+f 2146//1 2147//1 2110//1
+f 2110//1 2147//1 2111//1
+f 2147//1 2148//1 2111//1
+f 2111//1 2148//1 2112//1
+f 2148//1 2149//1 2112//1
+f 2112//1 2149//1 2113//1
+f 2149//1 2150//1 2113//1
+f 2113//1 2150//1 2114//1
+f 2150//1 2151//1 2114//1
+f 2114//1 2151//1 2115//1
+f 2151//1 2152//1 2115//1
+f 2115//1 2152//1 2116//1
+f 2152//1 2153//1 2116//1
+f 2116//1 2153//1 2117//1
+f 2153//1 2154//1 2117//1
+f 2117//1 2154//1 2118//1
+f 2154//1 2155//1 2118//1
+f 2118//1 2155//1 2119//1
+f 2155//1 2156//1 2119//1
+f 2119//1 2156//1 2120//1
+f 2156//1 2157//1 2120//1
+f 2120//1 2157//1 2121//1
+f 2157//1 2158//1 2121//1
+f 2121//1 2158//1 2122//1
+f 2158//1 2159//1 2122//1
+f 2122//1 2159//1 2123//1
+f 2159//1 2160//1 2123//1
+f 2123//1 2160//1 2124//1
+f 2160//1 2161//1 2124//1
+f 2124//1 2161//1 2125//1
+f 2161//1 2162//1 2125//1
+f 2125//1 2162//1 2126//1
+f 2162//1 2163//1 2126//1
+f 2126//1 2163//1 2127//1
+f 2163//1 2164//1 2127//1
+f 2127//1 2164//1 2128//1
+f 2164//1 2165//1 2128//1
+f 2128//1 2165//1 2129//1
+f 2165//1 2166//1 2129//1
+f 2129//1 2166//1 2130//1
+f 2166//1 2167//1 2130//1
+f 2130//1 2167//1 2131//1
+f 2167//1 2168//1 2131//1
+f 2131//1 2168//1 2132//1
+f 2168//1 2169//1 2132//1
+f 2132//1 2169//1 2133//1
+f 2169//1 2170//1 2133//1
+f 2133//1 2170//1 2134//1
+f 2170//1 2171//1 2134//1
+f 2134//1 2171//1 2135//1
+f 2171//1 2172//1 2135//1
+f 2135//1 2172//1 2136//1
+f 2172//1 2173//1 2136//1
+f 2136//1 2173//1 2137//1
+f 2173//1 2174//1 2137//1
+f 2137//1 2174//1 2138//1
+f 2174//1 2175//1 2138//1
+f 2138//1 2175//1 2139//1
+f 2175//1 2176//1 2139//1
+f 2139//1 2176//1 2140//1
+f 2176//1 2177//1 2140//1
+f 2140//1 2177//1 2141//1
+f 2177//1 2178//1 2141//1
+f 2141//1 2178//1 2142//1
+f 2178//1 2179//1 2142//1
+f 2142//1 2179//1 2143//1
+f 2179//1 2180//1 2143//1
+f 2143//1 2180//1 2144//1
+f 2180//1 2181//1 2144//1
+f 2144//1 2181//1 2145//1
+f 2181//1 2182//1 2145//1
+f 2145//1 2182//1 18//1
+f 2182//1 17//1 18//1
+f 92//1 2183//1 2146//1
+f 2183//1 2184//1 2146//1
+f 2146//1 2184//1 2147//1
+f 2184//1 2185//1 2147//1
+f 2147//1 2185//1 2148//1
+f 2185//1 2186//1 2148//1
+f 2148//1 2186//1 2149//1
+f 2186//1 2187//1 2149//1
+f 2149//1 2187//1 2150//1
+f 2187//1 2188//1 2150//1
+f 2150//1 2188//1 2151//1
+f 2188//1 2189//1 2151//1
+f 2151//1 2189//1 2152//1
+f 2189//1 2190//1 2152//1
+f 2152//1 2190//1 2153//1
+f 2190//1 2191//1 2153//1
+f 2153//1 2191//1 2154//1
+f 2191//1 2192//1 2154//1
+f 2154//1 2192//1 2155//1
+f 2192//1 2193//1 2155//1
+f 2155//1 2193//1 2156//1
+f 2193//1 2194//1 2156//1
+f 2156//1 2194//1 2157//1
+f 2194//1 2195//1 2157//1
+f 2157//1 2195//1 2158//1
+f 2195//1 2196//1 2158//1
+f 2158//1 2196//1 2159//1
+f 2196//1 2197//1 2159//1
+f 2159//1 2197//1 2160//1
+f 2197//1 2198//1 2160//1
+f 2160//1 2198//1 2161//1
+f 2198//1 2199//1 2161//1
+f 2161//1 2199//1 2162//1
+f 2199//1 2200//1 2162//1
+f 2162//1 2200//1 2163//1
+f 2200//1 2201//1 2163//1
+f 2163//1 2201//1 2164//1
+f 2201//1 2202//1 2164//1
+f 2164//1 2202//1 2165//1
+f 2202//1 2203//1 2165//1
+f 2165//1 2203//1 2166//1
+f 2203//1 2204//1 2166//1
+f 2166//1 2204//1 2167//1
+f 2204//1 2205//1 2167//1
+f 2167//1 2205//1 2168//1
+f 2205//1 2206//1 2168//1
+f 2168//1 2206//1 2169//1
+f 2206//1 2207//1 2169//1
+f 2169//1 2207//1 2170//1
+f 2207//1 2208//1 2170//1
+f 2170//1 2208//1 2171//1
+f 2208//1 2209//1 2171//1
+f 2171//1 2209//1 2172//1
+f 2209//1 2210//1 2172//1
+f 2172//1 2210//1 2173//1
+f 2210//1 2211//1 2173//1
+f 2173//1 2211//1 2174//1
+f 2211//1 2212//1 2174//1
+f 2174//1 2212//1 2175//1
+f 2212//1 2213//1 2175//1
+f 2175//1 2213//1 2176//1
+f 2213//1 2214//1 2176//1
+f 2176//1 2214//1 2177//1
+f 2214//1 2215//1 2177//1
+f 2177//1 2215//1 2178//1
+f 2215//1 2216//1 2178//1
+f 2178//1 2216//1 2179//1
+f 2216//1 2217//1 2179//1
+f 2179//1 2217//1 2180//1
+f 2217//1 2218//1 2180//1
+f 2180//1 2218//1 2181//1
+f 2218//1 2219//1 2181//1
+f 2181//1 2219//1 2182//1
+f 2219//1 2220//1 2182//1
+f 2182//1 2220//1 17//1
+f 2220//1 16//1 17//1
+f 93//1 2221//1 2183//1
+f 2221//1 2222//1 2183//1
+f 2183//1 2222//1 2184//1
+f 2222//1 2223//1 2184//1
+f 2184//1 2223//1 2185//1
+f 2223//1 2224//1 2185//1
+f 2185//1 2224//1 2186//1
+f 2224//1 2225//1 2186//1
+f 2186//1 2225//1 2187//1
+f 2225//1 2226//1 2187//1
+f 2187//1 2226//1 2188//1
+f 2226//1 2227//1 2188//1
+f 2188//1 2227//1 2189//1
+f 2227//1 2228//1 2189//1
+f 2189//1 2228//1 2190//1
+f 2228//1 2229//1 2190//1
+f 2190//1 2229//1 2191//1
+f 2229//1 2230//1 2191//1
+f 2191//1 2230//1 2192//1
+f 2230//1 2231//1 2192//1
+f 2192//1 2231//1 2193//1
+f 2231//1 2232//1 2193//1
+f 2193//1 2232//1 2194//1
+f 2232//1 2233//1 2194//1
+f 2194//1 2233//1 2195//1
+f 2233//1 2234//1 2195//1
+f 2195//1 2234//1 2196//1
+f 2234//1 2235//1 2196//1
+f 2196//1 2235//1 2197//1
+f 2235//1 2236//1 2197//1
+f 2197//1 2236//1 2198//1
+f 2236//1 2237//1 2198//1
+f 2198//1 2237//1 2199//1
+f 2237//1 2238//1 2199//1
+f 2199//1 2238//1 2200//1
+f 2238//1 2239//1 2200//1
+f 2200//1 2239//1 2201//1
+f 2239//1 2240//1 2201//1
+f 2201//1 2240//1 2202//1
+f 2240//1 2241//1 2202//1
+f 2202//1 2241//1 2203//1
+f 2241//1 2242//1 2203//1
+f 2203//1 2242//1 2204//1
+f 2242//1 2243//1 2204//1
+f 2204//1 2243//1 2205//1
+f 2243//1 2244//1 2205//1
+f 2205//1 2244//1 2206//1
+f 2244//1 2245//1 2206//1
+f 2206//1 2245//1 2207//1
+f 2245//1 2246//1 2207//1
+f 2207//1 2246//1 2208//1
+f 2246//1 2247//1 2208//1
+f 2208//1 2247//1 2209//1
+f 2247//1 2248//1 2209//1
+f 2209//1 2248//1 2210//1
+f 2248//1 2249//1 2210//1
+f 2210//1 2249//1 2211//1
+f 2249//1 2250//1 2211//1
+f 2211//1 2250//1 2212//1
+f 2250//1 2251//1 2212//1
+f 2212//1 2251//1 2213//1
+f 2251//1 2252//1 2213//1
+f 2213//1 2252//1 2214//1
+f 2252//1 2253//1 2214//1
+f 2214//1 2253//1 2215//1
+f 2253//1 2254//1 2215//1
+f 2215//1 2254//1 2216//1
+f 2254//1 2255//1 2216//1
+f 2216//1 2255//1 2217//1
+f 2255//1 2256//1 2217//1
+f 2217//1 2256//1 2218//1
+f 2256//1 2257//1 2218//1
+f 2218//1 2257//1 2219//1
+f 2257//1 2258//1 2219//1
+f 2219//1 2258//1 2220//1
+f 2258//1 2259//1 2220//1
+f 2220//1 2259//1 16//1
+f 2259//1 15//1 16//1
+f 94//1 2260//1 2221//1
+f 2260//1 2261//1 2221//1
+f 2221//1 2261//1 2222//1
+f 2261//1 2262//1 2222//1
+f 2222//1 2262//1 2223//1
+f 2262//1 2263//1 2223//1
+f 2223//1 2263//1 2224//1
+f 2263//1 2264//1 2224//1
+f 2224//1 2264//1 2225//1
+f 2264//1 2265//1 2225//1
+f 2225//1 2265//1 2226//1
+f 2265//1 2266//1 2226//1
+f 2226//1 2266//1 2227//1
+f 2266//1 2267//1 2227//1
+f 2227//1 2267//1 2228//1
+f 2267//1 2268//1 2228//1
+f 2228//1 2268//1 2229//1
+f 2268//1 2269//1 2229//1
+f 2229//1 2269//1 2230//1
+f 2269//1 2270//1 2230//1
+f 2230//1 2270//1 2231//1
+f 2270//1 2271//1 2231//1
+f 2231//1 2271//1 2232//1
+f 2271//1 2272//1 2232//1
+f 2232//1 2272//1 2233//1
+f 2272//1 2273//1 2233//1
+f 2233//1 2273//1 2234//1
+f 2273//1 2274//1 2234//1
+f 2234//1 2274//1 2235//1
+f 2274//1 2275//1 2235//1
+f 2235//1 2275//1 2236//1
+f 2275//1 2276//1 2236//1
+f 2236//1 2276//1 2237//1
+f 2276//1 2277//1 2237//1
+f 2237//1 2277//1 2238//1
+f 2277//1 2278//1 2238//1
+f 2238//1 2278//1 2239//1
+f 2278//1 2279//1 2239//1
+f 2239//1 2279//1 2240//1
+f 2279//1 2280//1 2240//1
+f 2240//1 2280//1 2241//1
+f 2280//1 2281//1 2241//1
+f 2241//1 2281//1 2242//1
+f 2281//1 2282//1 2242//1
+f 2242//1 2282//1 2243//1
+f 2282//1 2283//1 2243//1
+f 2243//1 2283//1 2244//1
+f 2283//1 2284//1 2244//1
+f 2244//1 2284//1 2245//1
+f 2284//1 2285//1 2245//1
+f 2245//1 2285//1 2246//1
+f 2285//1 2286//1 2246//1
+f 2246//1 2286//1 2247//1
+f 2286//1 2287//1 2247//1
+f 2247//1 2287//1 2248//1
+f 2287//1 2288//1 2248//1
+f 2248//1 2288//1 2249//1
+f 2288//1 2289//1 2249//1
+f 2249//1 2289//1 2250//1
+f 2289//1 2290//1 2250//1
+f 2250//1 2290//1 2251//1
+f 2290//1 2291//1 2251//1
+f 2251//1 2291//1 2252//1
+f 2291//1 2292//1 2252//1
+f 2252//1 2292//1 2253//1
+f 2292//1 2293//1 2253//1
+f 2253//1 2293//1 2254//1
+f 2293//1 2294//1 2254//1
+f 2254//1 2294//1 2255//1
+f 2294//1 2295//1 2255//1
+f 2255//1 2295//1 2256//1
+f 2295//1 2296//1 2256//1
+f 2256//1 2296//1 2257//1
+f 2296//1 2297//1 2257//1
+f 2257//1 2297//1 2258//1
+f 2297//1 2298//1 2258//1
+f 2258//1 2298//1 2259//1
+f 2298//1 2299//1 2259//1
+f 2259//1 2299//1 15//1
+f 2299//1 14//1 15//1
+f 95//1 2300//1 2260//1
+f 2300//1 2301//1 2260//1
+f 2260//1 2301//1 2261//1
+f 2301//1 2302//1 2261//1
+f 2261//1 2302//1 2262//1
+f 2302//1 2303//1 2262//1
+f 2262//1 2303//1 2263//1
+f 2303//1 2304//1 2263//1
+f 2263//1 2304//1 2264//1
+f 2304//1 2305//1 2264//1
+f 2264//1 2305//1 2265//1
+f 2305//1 2306//1 2265//1
+f 2265//1 2306//1 2266//1
+f 2306//1 2307//1 2266//1
+f 2266//1 2307//1 2267//1
+f 2307//1 2308//1 2267//1
+f 2267//1 2308//1 2268//1
+f 2308//1 2309//1 2268//1
+f 2268//1 2309//1 2269//1
+f 2309//1 2310//1 2269//1
+f 2269//1 2310//1 2270//1
+f 2310//1 2311//1 2270//1
+f 2270//1 2311//1 2271//1
+f 2311//1 2312//1 2271//1
+f 2271//1 2312//1 2272//1
+f 2312//1 2313//1 2272//1
+f 2272//1 2313//1 2273//1
+f 2313//1 2314//1 2273//1
+f 2273//1 2314//1 2274//1
+f 2314//1 2315//1 2274//1
+f 2274//1 2315//1 2275//1
+f 2315//1 2316//1 2275//1
+f 2275//1 2316//1 2276//1
+f 2316//1 2317//1 2276//1
+f 2276//1 2317//1 2277//1
+f 2317//1 2318//1 2277//1
+f 2277//1 2318//1 2278//1
+f 2318//1 2319//1 2278//1
+f 2278//1 2319//1 2279//1
+f 2319//1 2320//1 2279//1
+f 2279//1 2320//1 2280//1
+f 2320//1 2321//1 2280//1
+f 2280//1 2321//1 2281//1
+f 2321//1 2322//1 2281//1
+f 2281//1 2322//1 2282//1
+f 2322//1 2323//1 2282//1
+f 2282//1 2323//1 2283//1
+f 2323//1 2324//1 2283//1
+f 2283//1 2324//1 2284//1
+f 2324//1 2325//1 2284//1
+f 2284//1 2325//1 2285//1
+f 2325//1 2326//1 2285//1
+f 2285//1 2326//1 2286//1
+f 2326//1 2327//1 2286//1
+f 2286//1 2327//1 2287//1
+f 2327//1 2328//1 2287//1
+f 2287//1 2328//1 2288//1
+f 2328//1 2329//1 2288//1
+f 2288//1 2329//1 2289//1
+f 2329//1 2330//1 2289//1
+f 2289//1 2330//1 2290//1
+f 2330//1 2331//1 2290//1
+f 2290//1 2331//1 2291//1
+f 2331//1 2332//1 2291//1
+f 2291//1 2332//1 2292//1
+f 2332//1 2333//1 2292//1
+f 2292//1 2333//1 2293//1
+f 2333//1 2334//1 2293//1
+f 2293//1 2334//1 2294//1
+f 2334//1 2335//1 2294//1
+f 2294//1 2335//1 2295//1
+f 2335//1 2336//1 2295//1
+f 2295//1 2336//1 2296//1
+f 2336//1 2337//1 2296//1
+f 2296//1 2337//1 2297//1
+f 2337//1 2338//1 2297//1
+f 2297//1 2338//1 2298//1
+f 2338//1 2339//1 2298//1
+f 2298//1 2339//1 2299//1
+f 2339//1 2340//1 2299//1
+f 2299//1 2340//1 14//1
+f 2340//1 13//1 14//1
+f 96//1 2341//1 2300//1
+f 2341//1 2342//1 2300//1
+f 2300//1 2342//1 2301//1
+f 2342//1 2343//1 2301//1
+f 2301//1 2343//1 2302//1
+f 2343//1 2344//1 2302//1
+f 2302//1 2344//1 2303//1
+f 2344//1 2345//1 2303//1
+f 2303//1 2345//1 2304//1
+f 2345//1 2346//1 2304//1
+f 2304//1 2346//1 2305//1
+f 2346//1 2347//1 2305//1
+f 2305//1 2347//1 2306//1
+f 2347//1 2348//1 2306//1
+f 2306//1 2348//1 2307//1
+f 2348//1 2349//1 2307//1
+f 2307//1 2349//1 2308//1
+f 2349//1 2350//1 2308//1
+f 2308//1 2350//1 2309//1
+f 2350//1 2351//1 2309//1
+f 2309//1 2351//1 2310//1
+f 2351//1 2352//1 2310//1
+f 2310//1 2352//1 2311//1
+f 2352//1 2353//1 2311//1
+f 2311//1 2353//1 2312//1
+f 2353//1 2354//1 2312//1
+f 2312//1 2354//1 2313//1
+f 2354//1 2355//1 2313//1
+f 2313//1 2355//1 2314//1
+f 2355//1 2356//1 2314//1
+f 2314//1 2356//1 2315//1
+f 2356//1 2357//1 2315//1
+f 2315//1 2357//1 2316//1
+f 2357//1 2358//1 2316//1
+f 2316//1 2358//1 2317//1
+f 2358//1 2359//1 2317//1
+f 2317//1 2359//1 2318//1
+f 2359//1 2360//1 2318//1
+f 2318//1 2360//1 2319//1
+f 2360//1 2361//1 2319//1
+f 2319//1 2361//1 2320//1
+f 2361//1 2362//1 2320//1
+f 2320//1 2362//1 2321//1
+f 2362//1 2363//1 2321//1
+f 2321//1 2363//1 2322//1
+f 2363//1 2364//1 2322//1
+f 2322//1 2364//1 2323//1
+f 2364//1 2365//1 2323//1
+f 2323//1 2365//1 2324//1
+f 2365//1 2366//1 2324//1
+f 2324//1 2366//1 2325//1
+f 2366//1 2367//1 2325//1
+f 2325//1 2367//1 2326//1
+f 2367//1 2368//1 2326//1
+f 2326//1 2368//1 2327//1
+f 2368//1 2369//1 2327//1
+f 2327//1 2369//1 2328//1
+f 2369//1 2370//1 2328//1
+f 2328//1 2370//1 2329//1
+f 2370//1 2371//1 2329//1
+f 2329//1 2371//1 2330//1
+f 2371//1 2372//1 2330//1
+f 2330//1 2372//1 2331//1
+f 2372//1 2373//1 2331//1
+f 2331//1 2373//1 2332//1
+f 2373//1 2374//1 2332//1
+f 2332//1 2374//1 2333//1
+f 2374//1 2375//1 2333//1
+f 2333//1 2375//1 2334//1
+f 2375//1 2376//1 2334//1
+f 2334//1 2376//1 2335//1
+f 2376//1 2377//1 2335//1
+f 2335//1 2377//1 2336//1
+f 2377//1 2378//1 2336//1
+f 2336//1 2378//1 2337//1
+f 2378//1 2379//1 2337//1
+f 2337//1 2379//1 2338//1
+f 2379//1 2380//1 2338//1
+f 2338//1 2380//1 2339//1
+f 2380//1 2381//1 2339//1
+f 2339//1 2381//1 2340//1
+f 2381//1 2382//1 2340//1
+f 2340//1 2382//1 13//1
+f 2382//1 12//1 13//1
+f 97//1 2383//1 2341//1
+f 2383//1 2384//1 2341//1
+f 2341//1 2384//1 2342//1
+f 2384//1 2385//1 2342//1
+f 2342//1 2385//1 2343//1
+f 2385//1 2386//1 2343//1
+f 2343//1 2386//1 2344//1
+f 2386//1 2387//1 2344//1
+f 2344//1 2387//1 2345//1
+f 2387//1 2388//1 2345//1
+f 2345//1 2388//1 2346//1
+f 2388//1 2389//1 2346//1
+f 2346//1 2389//1 2347//1
+f 2389//1 2390//1 2347//1
+f 2347//1 2390//1 2348//1
+f 2390//1 2391//1 2348//1
+f 2348//1 2391//1 2349//1
+f 2391//1 2392//1 2349//1
+f 2349//1 2392//1 2350//1
+f 2392//1 2393//1 2350//1
+f 2350//1 2393//1 2351//1
+f 2393//1 2394//1 2351//1
+f 2351//1 2394//1 2352//1
+f 2394//1 2395//1 2352//1
+f 2352//1 2395//1 2353//1
+f 2395//1 2396//1 2353//1
+f 2353//1 2396//1 2354//1
+f 2396//1 2397//1 2354//1
+f 2354//1 2397//1 2355//1
+f 2397//1 2398//1 2355//1
+f 2355//1 2398//1 2356//1
+f 2398//1 2399//1 2356//1
+f 2356//1 2399//1 2357//1
+f 2399//1 2400//1 2357//1
+f 2357//1 2400//1 2358//1
+f 2400//1 2401//1 2358//1
+f 2358//1 2401//1 2359//1
+f 2401//1 2402//1 2359//1
+f 2359//1 2402//1 2360//1
+f 2402//1 2403//1 2360//1
+f 2360//1 2403//1 2361//1
+f 2403//1 2404//1 2361//1
+f 2361//1 2404//1 2362//1
+f 2404//1 2405//1 2362//1
+f 2362//1 2405//1 2363//1
+f 2405//1 2406//1 2363//1
+f 2363//1 2406//1 2364//1
+f 2406//1 2407//1 2364//1
+f 2364//1 2407//1 2365//1
+f 2407//1 2408//1 2365//1
+f 2365//1 2408//1 2366//1
+f 2408//1 2409//1 2366//1
+f 2366//1 2409//1 2367//1
+f 2409//1 2410//1 2367//1
+f 2367//1 2410//1 2368//1
+f 2410//1 2411//1 2368//1
+f 2368//1 2411//1 2369//1
+f 2411//1 2412//1 2369//1
+f 2369//1 2412//1 2370//1
+f 2412//1 2413//1 2370//1
+f 2370//1 2413//1 2371//1
+f 2413//1 2414//1 2371//1
+f 2371//1 2414//1 2372//1
+f 2414//1 2415//1 2372//1
+f 2372//1 2415//1 2373//1
+f 2415//1 2416//1 2373//1
+f 2373//1 2416//1 2374//1
+f 2416//1 2417//1 2374//1
+f 2374//1 2417//1 2375//1
+f 2417//1 2418//1 2375//1
+f 2375//1 2418//1 2376//1
+f 2418//1 2419//1 2376//1
+f 2376//1 2419//1 2377//1
+f 2419//1 2420//1 2377//1
+f 2377//1 2420//1 2378//1
+f 2420//1 2421//1 2378//1
+f 2378//1 2421//1 2379//1
+f 2421//1 2422//1 2379//1
+f 2379//1 2422//1 2380//1
+f 2422//1 2423//1 2380//1
+f 2380//1 2423//1 2381//1
+f 2423//1 2424//1 2381//1
+f 2381//1 2424//1 2382//1
+f 2424//1 2425//1 2382//1
+f 2382//1 2425//1 12//1
+f 2425//1 11//1 12//1
+f 98//1 2426//1 2383//1
+f 2426//1 2427//1 2383//1
+f 2383//1 2427//1 2384//1
+f 2427//1 2428//1 2384//1
+f 2384//1 2428//1 2385//1
+f 2428//1 2429//1 2385//1
+f 2385//1 2429//1 2386//1
+f 2429//1 2430//1 2386//1
+f 2386//1 2430//1 2387//1
+f 2430//1 2431//1 2387//1
+f 2387//1 2431//1 2388//1
+f 2431//1 2432//1 2388//1
+f 2388//1 2432//1 2389//1
+f 2432//1 2433//1 2389//1
+f 2389//1 2433//1 2390//1
+f 2433//1 2434//1 2390//1
+f 2390//1 2434//1 2391//1
+f 2434//1 2435//1 2391//1
+f 2391//1 2435//1 2392//1
+f 2435//1 2436//1 2392//1
+f 2392//1 2436//1 2393//1
+f 2436//1 2437//1 2393//1
+f 2393//1 2437//1 2394//1
+f 2437//1 2438//1 2394//1
+f 2394//1 2438//1 2395//1
+f 2438//1 2439//1 2395//1
+f 2395//1 2439//1 2396//1
+f 2439//1 2440//1 2396//1
+f 2396//1 2440//1 2397//1
+f 2440//1 2441//1 2397//1
+f 2397//1 2441//1 2398//1
+f 2441//1 2442//1 2398//1
+f 2398//1 2442//1 2399//1
+f 2442//1 2443//1 2399//1
+f 2399//1 2443//1 2400//1
+f 2443//1 2444//1 2400//1
+f 2400//1 2444//1 2401//1
+f 2444//1 2445//1 2401//1
+f 2401//1 2445//1 2402//1
+f 2445//1 2446//1 2402//1
+f 2402//1 2446//1 2403//1
+f 2446//1 2447//1 2403//1
+f 2403//1 2447//1 2404//1
+f 2447//1 2448//1 2404//1
+f 2404//1 2448//1 2405//1
+f 2448//1 2449//1 2405//1
+f 2405//1 2449//1 2406//1
+f 2449//1 2450//1 2406//1
+f 2406//1 2450//1 2407//1
+f 2450//1 2451//1 2407//1
+f 2407//1 2451//1 2408//1
+f 2451//1 2452//1 2408//1
+f 2408//1 2452//1 2409//1
+f 2452//1 2453//1 2409//1
+f 2409//1 2453//1 2410//1
+f 2453//1 2454//1 2410//1
+f 2410//1 2454//1 2411//1
+f 2454//1 2455//1 2411//1
+f 2411//1 2455//1 2412//1
+f 2455//1 2456//1 2412//1
+f 2412//1 2456//1 2413//1
+f 2456//1 2457//1 2413//1
+f 2413//1 2457//1 2414//1
+f 2457//1 2458//1 2414//1
+f 2414//1 2458//1 2415//1
+f 2458//1 2459//1 2415//1
+f 2415//1 2459//1 2416//1
+f 2459//1 2460//1 2416//1
+f 2416//1 2460//1 2417//1
+f 2460//1 2461//1 2417//1
+f 2417//1 2461//1 2418//1
+f 2461//1 2462//1 2418//1
+f 2418//1 2462//1 2419//1
+f 2462//1 2463//1 2419//1
+f 2419//1 2463//1 2420//1
+f 2463//1 2464//1 2420//1
+f 2420//1 2464//1 2421//1
+f 2464//1 2465//1 2421//1
+f 2421//1 2465//1 2422//1
+f 2465//1 2466//1 2422//1
+f 2422//1 2466//1 2423//1
+f 2466//1 2467//1 2423//1
+f 2423//1 2467//1 2424//1
+f 2467//1 2468//1 2424//1
+f 2424//1 2468//1 2425//1
+f 2468//1 2469//1 2425//1
+f 2425//1 2469//1 11//1
+f 2469//1 10//1 11//1
+f 99//1 2470//1 2426//1
+f 2470//1 2471//1 2426//1
+f 2426//1 2471//1 2427//1
+f 2471//1 2472//1 2427//1
+f 2427//1 2472//1 2428//1
+f 2472//1 2473//1 2428//1
+f 2428//1 2473//1 2429//1
+f 2473//1 2474//1 2429//1
+f 2429//1 2474//1 2430//1
+f 2474//1 2475//1 2430//1
+f 2430//1 2475//1 2431//1
+f 2475//1 2476//1 2431//1
+f 2431//1 2476//1 2432//1
+f 2476//1 2477//1 2432//1
+f 2432//1 2477//1 2433//1
+f 2477//1 2478//1 2433//1
+f 2433//1 2478//1 2434//1
+f 2478//1 2479//1 2434//1
+f 2434//1 2479//1 2435//1
+f 2479//1 2480//1 2435//1
+f 2435//1 2480//1 2436//1
+f 2480//1 2481//1 2436//1
+f 2436//1 2481//1 2437//1
+f 2481//1 2482//1 2437//1
+f 2437//1 2482//1 2438//1
+f 2482//1 2483//1 2438//1
+f 2438//1 2483//1 2439//1
+f 2483//1 2484//1 2439//1
+f 2439//1 2484//1 2440//1
+f 2484//1 2485//1 2440//1
+f 2440//1 2485//1 2441//1
+f 2485//1 2486//1 2441//1
+f 2441//1 2486//1 2442//1
+f 2486//1 2487//1 2442//1
+f 2442//1 2487//1 2443//1
+f 2487//1 2488//1 2443//1
+f 2443//1 2488//1 2444//1
+f 2488//1 2489//1 2444//1
+f 2444//1 2489//1 2445//1
+f 2489//1 2490//1 2445//1
+f 2445//1 2490//1 2446//1
+f 2490//1 2491//1 2446//1
+f 2446//1 2491//1 2447//1
+f 2491//1 2492//1 2447//1
+f 2447//1 2492//1 2448//1
+f 2492//1 2493//1 2448//1
+f 2448//1 2493//1 2449//1
+f 2493//1 2494//1 2449//1
+f 2449//1 2494//1 2450//1
+f 2494//1 2495//1 2450//1
+f 2450//1 2495//1 2451//1
+f 2495//1 2496//1 2451//1
+f 2451//1 2496//1 2452//1
+f 2496//1 2497//1 2452//1
+f 2452//1 2497//1 2453//1
+f 2497//1 2498//1 2453//1
+f 2453//1 2498//1 2454//1
+f 2498//1 2499//1 2454//1
+f 2454//1 2499//1 2455//1
+f 2499//1 2500//1 2455//1
+f 2455//1 2500//1 2456//1
+f 2500//1 2501//1 2456//1
+f 2456//1 2501//1 2457//1
+f 2501//1 2502//1 2457//1
+f 2457//1 2502//1 2458//1
+f 2502//1 2503//1 2458//1
+f 2458//1 2503//1 2459//1
+f 2503//1 2504//1 2459//1
+f 2459//1 2504//1 2460//1
+f 2504//1 2505//1 2460//1
+f 2460//1 2505//1 2461//1
+f 2505//1 2506//1 2461//1
+f 2461//1 2506//1 2462//1
+f 2506//1 2507//1 2462//1
+f 2462//1 2507//1 2463//1
+f 2507//1 2508//1 2463//1
+f 2463//1 2508//1 2464//1
+f 2508//1 2509//1 2464//1
+f 2464//1 2509//1 2465//1
+f 2509//1 2510//1 2465//1
+f 2465//1 2510//1 2466//1
+f 2510//1 2511//1 2466//1
+f 2466//1 2511//1 2467//1
+f 2511//1 2512//1 2467//1
+f 2467//1 2512//1 2468//1
+f 2512//1 2513//1 2468//1
+f 2468//1 2513//1 2469//1
+f 2513//1 2514//1 2469//1
+f 2469//1 2514//1 10//1
+f 2514//1 9//1 10//1
+f 100//1 2515//1 2470//1
+f 2515//1 2516//1 2470//1
+f 2470//1 2516//1 2471//1
+f 2516//1 2517//1 2471//1
+f 2471//1 2517//1 2472//1
+f 2517//1 2518//1 2472//1
+f 2472//1 2518//1 2473//1
+f 2518//1 2519//1 2473//1
+f 2473//1 2519//1 2474//1
+f 2519//1 2520//1 2474//1
+f 2474//1 2520//1 2475//1
+f 2520//1 2521//1 2475//1
+f 2475//1 2521//1 2476//1
+f 2521//1 2522//1 2476//1
+f 2476//1 2522//1 2477//1
+f 2522//1 2523//1 2477//1
+f 2477//1 2523//1 2478//1
+f 2523//1 2524//1 2478//1
+f 2478//1 2524//1 2479//1
+f 2524//1 2525//1 2479//1
+f 2479//1 2525//1 2480//1
+f 2525//1 2526//1 2480//1
+f 2480//1 2526//1 2481//1
+f 2526//1 2527//1 2481//1
+f 2481//1 2527//1 2482//1
+f 2527//1 2528//1 2482//1
+f 2482//1 2528//1 2483//1
+f 2528//1 2529//1 2483//1
+f 2483//1 2529//1 2484//1
+f 2529//1 2530//1 2484//1
+f 2484//1 2530//1 2485//1
+f 2530//1 2531//1 2485//1
+f 2485//1 2531//1 2486//1
+f 2531//1 2532//1 2486//1
+f 2486//1 2532//1 2487//1
+f 2532//1 2533//1 2487//1
+f 2487//1 2533//1 2488//1
+f 2533//1 2534//1 2488//1
+f 2488//1 2534//1 2489//1
+f 2534//1 2535//1 2489//1
+f 2489//1 2535//1 2490//1
+f 2535//1 2536//1 2490//1
+f 2490//1 2536//1 2491//1
+f 2536//1 2537//1 2491//1
+f 2491//1 2537//1 2492//1
+f 2537//1 2538//1 2492//1
+f 2492//1 2538//1 2493//1
+f 2538//1 2539//1 2493//1
+f 2493//1 2539//1 2494//1
+f 2539//1 2540//1 2494//1
+f 2494//1 2540//1 2495//1
+f 2540//1 2541//1 2495//1
+f 2495//1 2541//1 2496//1
+f 2541//1 2542//1 2496//1
+f 2496//1 2542//1 2497//1
+f 2542//1 2543//1 2497//1
+f 2497//1 2543//1 2498//1
+f 2543//1 2544//1 2498//1
+f 2498//1 2544//1 2499//1
+f 2544//1 2545//1 2499//1
+f 2499//1 2545//1 2500//1
+f 2545//1 2546//1 2500//1
+f 2500//1 2546//1 2501//1
+f 2546//1 2547//1 2501//1
+f 2501//1 2547//1 2502//1
+f 2547//1 2548//1 2502//1
+f 2502//1 2548//1 2503//1
+f 2548//1 2549//1 2503//1
+f 2503//1 2549//1 2504//1
+f 2549//1 2550//1 2504//1
+f 2504//1 2550//1 2505//1
+f 2550//1 2551//1 2505//1
+f 2505//1 2551//1 2506//1
+f 2551//1 2552//1 2506//1
+f 2506//1 2552//1 2507//1
+f 2552//1 2553//1 2507//1
+f 2507//1 2553//1 2508//1
+f 2553//1 2554//1 2508//1
+f 2508//1 2554//1 2509//1
+f 2554//1 2555//1 2509//1
+f 2509//1 2555//1 2510//1
+f 2555//1 2556//1 2510//1
+f 2510//1 2556//1 2511//1
+f 2556//1 2557//1 2511//1
+f 2511//1 2557//1 2512//1
+f 2557//1 2558//1 2512//1
+f 2512//1 2558//1 2513//1
+f 2558//1 2559//1 2513//1
+f 2513//1 2559//1 2514//1
+f 2559//1 2560//1 2514//1
+f 2514//1 2560//1 9//1
+f 2560//1 8//1 9//1
+f 101//1 2561//1 2515//1
+f 2561//1 2562//1 2515//1
+f 2515//1 2562//1 2516//1
+f 2562//1 2563//1 2516//1
+f 2516//1 2563//1 2517//1
+f 2563//1 2564//1 2517//1
+f 2517//1 2564//1 2518//1
+f 2564//1 2565//1 2518//1
+f 2518//1 2565//1 2519//1
+f 2565//1 2566//1 2519//1
+f 2519//1 2566//1 2520//1
+f 2566//1 2567//1 2520//1
+f 2520//1 2567//1 2521//1
+f 2567//1 2568//1 2521//1
+f 2521//1 2568//1 2522//1
+f 2568//1 2569//1 2522//1
+f 2522//1 2569//1 2523//1
+f 2569//1 2570//1 2523//1
+f 2523//1 2570//1 2524//1
+f 2570//1 2571//1 2524//1
+f 2524//1 2571//1 2525//1
+f 2571//1 2572//1 2525//1
+f 2525//1 2572//1 2526//1
+f 2572//1 2573//1 2526//1
+f 2526//1 2573//1 2527//1
+f 2573//1 2574//1 2527//1
+f 2527//1 2574//1 2528//1
+f 2574//1 2575//1 2528//1
+f 2528//1 2575//1 2529//1
+f 2575//1 2576//1 2529//1
+f 2529//1 2576//1 2530//1
+f 2576//1 2577//1 2530//1
+f 2530//1 2577//1 2531//1
+f 2577//1 2578//1 2531//1
+f 2531//1 2578//1 2532//1
+f 2578//1 2579//1 2532//1
+f 2532//1 2579//1 2533//1
+f 2579//1 2580//1 2533//1
+f 2533//1 2580//1 2534//1
+f 2580//1 2581//1 2534//1
+f 2534//1 2581//1 2535//1
+f 2581//1 2582//1 2535//1
+f 2535//1 2582//1 2536//1
+f 2582//1 2583//1 2536//1
+f 2536//1 2583//1 2537//1
+f 2583//1 2584//1 2537//1
+f 2537//1 2584//1 2538//1
+f 2584//1 2585//1 2538//1
+f 2538//1 2585//1 2539//1
+f 2585//1 2586//1 2539//1
+f 2539//1 2586//1 2540//1
+f 2586//1 2587//1 2540//1
+f 2540//1 2587//1 2541//1
+f 2587//1 2588//1 2541//1
+f 2541//1 2588//1 2542//1
+f 2588//1 2589//1 2542//1
+f 2542//1 2589//1 2543//1
+f 2589//1 2590//1 2543//1
+f 2543//1 2590//1 2544//1
+f 2590//1 2591//1 2544//1
+f 2544//1 2591//1 2545//1
+f 2591//1 2592//1 2545//1
+f 2545//1 2592//1 2546//1
+f 2592//1 2593//1 2546//1
+f 2546//1 2593//1 2547//1
+f 2593//1 2594//1 2547//1
+f 2547//1 2594//1 2548//1
+f 2594//1 2595//1 2548//1
+f 2548//1 2595//1 2549//1
+f 2595//1 2596//1 2549//1
+f 2549//1 2596//1 2550//1
+f 2596//1 2597//1 2550//1
+f 2550//1 2597//1 2551//1
+f 2597//1 2598//1 2551//1
+f 2551//1 2598//1 2552//1
+f 2598//1 2599//1 2552//1
+f 2552//1 2599//1 2553//1
+f 2599//1 2600//1 2553//1
+f 2553//1 2600//1 2554//1
+f 2600//1 2601//1 2554//1
+f 2554//1 2601//1 2555//1
+f 2601//1 2602//1 2555//1
+f 2555//1 2602//1 2556//1
+f 2602//1 2603//1 2556//1
+f 2556//1 2603//1 2557//1
+f 2603//1 2604//1 2557//1
+f 2557//1 2604//1 2558//1
+f 2604//1 2605//1 2558//1
+f 2558//1 2605//1 2559//1
+f 2605//1 2606//1 2559//1
+f 2559//1 2606//1 2560//1
+f 2606//1 2607//1 2560//1
+f 2560//1 2607//1 8//1
+f 2607//1 7//1 8//1
+f 102//1 2608//1 2561//1
+f 2608//1 2609//1 2561//1
+f 2561//1 2609//1 2562//1
+f 2609//1 2610//1 2562//1
+f 2562//1 2610//1 2563//1
+f 2610//1 2611//1 2563//1
+f 2563//1 2611//1 2564//1
+f 2611//1 2612//1 2564//1
+f 2564//1 2612//1 2565//1
+f 2612//1 2613//1 2565//1
+f 2565//1 2613//1 2566//1
+f 2613//1 2614//1 2566//1
+f 2566//1 2614//1 2567//1
+f 2614//1 2615//1 2567//1
+f 2567//1 2615//1 2568//1
+f 2615//1 2616//1 2568//1
+f 2568//1 2616//1 2569//1
+f 2616//1 2617//1 2569//1
+f 2569//1 2617//1 2570//1
+f 2617//1 2618//1 2570//1
+f 2570//1 2618//1 2571//1
+f 2618//1 2619//1 2571//1
+f 2571//1 2619//1 2572//1
+f 2619//1 2620//1 2572//1
+f 2572//1 2620//1 2573//1
+f 2620//1 2621//1 2573//1
+f 2573//1 2621//1 2574//1
+f 2621//1 2622//1 2574//1
+f 2574//1 2622//1 2575//1
+f 2622//1 2623//1 2575//1
+f 2575//1 2623//1 2576//1
+f 2623//1 2624//1 2576//1
+f 2576//1 2624//1 2577//1
+f 2624//1 2625//1 2577//1
+f 2577//1 2625//1 2578//1
+f 2625//1 2626//1 2578//1
+f 2578//1 2626//1 2579//1
+f 2626//1 2627//1 2579//1
+f 2579//1 2627//1 2580//1
+f 2627//1 2628//1 2580//1
+f 2580//1 2628//1 2581//1
+f 2628//1 2629//1 2581//1
+f 2581//1 2629//1 2582//1
+f 2629//1 2630//1 2582//1
+f 2582//1 2630//1 2583//1
+f 2630//1 2631//1 2583//1
+f 2583//1 2631//1 2584//1
+f 2631//1 2632//1 2584//1
+f 2584//1 2632//1 2585//1
+f 2632//1 2633//1 2585//1
+f 2585//1 2633//1 2586//1
+f 2633//1 2634//1 2586//1
+f 2586//1 2634//1 2587//1
+f 2634//1 2635//1 2587//1
+f 2587//1 2635//1 2588//1
+f 2635//1 2636//1 2588//1
+f 2588//1 2636//1 2589//1
+f 2636//1 2637//1 2589//1
+f 2589//1 2637//1 2590//1
+f 2637//1 2638//1 2590//1
+f 2590//1 2638//1 2591//1
+f 2638//1 2639//1 2591//1
+f 2591//1 2639//1 2592//1
+f 2639//1 2640//1 2592//1
+f 2592//1 2640//1 2593//1
+f 2640//1 2641//1 2593//1
+f 2593//1 2641//1 2594//1
+f 2641//1 2642//1 2594//1
+f 2594//1 2642//1 2595//1
+f 2642//1 2643//1 2595//1
+f 2595//1 2643//1 2596//1
+f 2643//1 2644//1 2596//1
+f 2596//1 2644//1 2597//1
+f 2644//1 2645//1 2597//1
+f 2597//1 2645//1 2598//1
+f 2645//1 2646//1 2598//1
+f 2598//1 2646//1 2599//1
+f 2646//1 2647//1 2599//1
+f 2599//1 2647//1 2600//1
+f 2647//1 2648//1 2600//1
+f 2600//1 2648//1 2601//1
+f 2648//1 2649//1 2601//1
+f 2601//1 2649//1 2602//1
+f 2649//1 2650//1 2602//1
+f 2602//1 2650//1 2603//1
+f 2650//1 2651//1 2603//1
+f 2603//1 2651//1 2604//1
+f 2651//1 2652//1 2604//1
+f 2604//1 2652//1 2605//1
+f 2652//1 2653//1 2605//1
+f 2605//1 2653//1 2606//1
+f 2653//1 2654//1 2606//1
+f 2606//1 2654//1 2607//1
+f 2654//1 2655//1 2607//1
+f 2607//1 2655//1 7//1
+f 2655//1 6//1 7//1
+f 103//1 2656//1 2608//1
+f 2656//1 2657//1 2608//1
+f 2608//1 2657//1 2609//1
+f 2657//1 2658//1 2609//1
+f 2609//1 2658//1 2610//1
+f 2658//1 2659//1 2610//1
+f 2610//1 2659//1 2611//1
+f 2659//1 2660//1 2611//1
+f 2611//1 2660//1 2612//1
+f 2660//1 2661//1 2612//1
+f 2612//1 2661//1 2613//1
+f 2661//1 2662//1 2613//1
+f 2613//1 2662//1 2614//1
+f 2662//1 2663//1 2614//1
+f 2614//1 2663//1 2615//1
+f 2663//1 2664//1 2615//1
+f 2615//1 2664//1 2616//1
+f 2664//1 2665//1 2616//1
+f 2616//1 2665//1 2617//1
+f 2665//1 2666//1 2617//1
+f 2617//1 2666//1 2618//1
+f 2666//1 2667//1 2618//1
+f 2618//1 2667//1 2619//1
+f 2667//1 2668//1 2619//1
+f 2619//1 2668//1 2620//1
+f 2668//1 2669//1 2620//1
+f 2620//1 2669//1 2621//1
+f 2669//1 2670//1 2621//1
+f 2621//1 2670//1 2622//1
+f 2670//1 2671//1 2622//1
+f 2622//1 2671//1 2623//1
+f 2671//1 2672//1 2623//1
+f 2623//1 2672//1 2624//1
+f 2672//1 2673//1 2624//1
+f 2624//1 2673//1 2625//1
+f 2673//1 2674//1 2625//1
+f 2625//1 2674//1 2626//1
+f 2674//1 2675//1 2626//1
+f 2626//1 2675//1 2627//1
+f 2675//1 2676//1 2627//1
+f 2627//1 2676//1 2628//1
+f 2676//1 2677//1 2628//1
+f 2628//1 2677//1 2629//1
+f 2677//1 2678//1 2629//1
+f 2629//1 2678//1 2630//1
+f 2678//1 2679//1 2630//1
+f 2630//1 2679//1 2631//1
+f 2679//1 2680//1 2631//1
+f 2631//1 2680//1 2632//1
+f 2680//1 2681//1 2632//1
+f 2632//1 2681//1 2633//1
+f 2681//1 2682//1 2633//1
+f 2633//1 2682//1 2634//1
+f 2682//1 2683//1 2634//1
+f 2634//1 2683//1 2635//1
+f 2683//1 2684//1 2635//1
+f 2635//1 2684//1 2636//1
+f 2684//1 2685//1 2636//1
+f 2636//1 2685//1 2637//1
+f 2685//1 2686//1 2637//1
+f 2637//1 2686//1 2638//1
+f 2686//1 2687//1 2638//1
+f 2638//1 2687//1 2639//1
+f 2687//1 2688//1 2639//1
+f 2639//1 2688//1 2640//1
+f 2688//1 2689//1 2640//1
+f 2640//1 2689//1 2641//1
+f 2689//1 2690//1 2641//1
+f 2641//1 2690//1 2642//1
+f 2690//1 2691//1 2642//1
+f 2642//1 2691//1 2643//1
+f 2691//1 2692//1 2643//1
+f 2643//1 2692//1 2644//1
+f 2692//1 2693//1 2644//1
+f 2644//1 2693//1 2645//1
+f 2693//1 2694//1 2645//1
+f 2645//1 2694//1 2646//1
+f 2694//1 2695//1 2646//1
+f 2646//1 2695//1 2647//1
+f 2695//1 2696//1 2647//1
+f 2647//1 2696//1 2648//1
+f 2696//1 2697//1 2648//1
+f 2648//1 2697//1 2649//1
+f 2697//1 2698//1 2649//1
+f 2649//1 2698//1 2650//1
+f 2698//1 2699//1 2650//1
+f 2650//1 2699//1 2651//1
+f 2699//1 2700//1 2651//1
+f 2651//1 2700//1 2652//1
+f 2700//1 2701//1 2652//1
+f 2652//1 2701//1 2653//1
+f 2701//1 2702//1 2653//1
+f 2653//1 2702//1 2654//1
+f 2702//1 2703//1 2654//1
+f 2654//1 2703//1 2655//1
+f 2703//1 2704//1 2655//1
+f 2655//1 2704//1 6//1
+f 2704//1 5//1 6//1
+f 104//1 254//1 2656//1
+f 254//1 253//1 2656//1
+f 2656//1 253//1 2657//1
+f 253//1 252//1 2657//1
+f 2657//1 252//1 2658//1
+f 252//1 251//1 2658//1
+f 2658//1 251//1 2659//1
+f 251//1 250//1 2659//1
+f 2659//1 250//1 2660//1
+f 250//1 249//1 2660//1
+f 2660//1 249//1 2661//1
+f 249//1 248//1 2661//1
+f 2661//1 248//1 2662//1
+f 248//1 247//1 2662//1
+f 2662//1 247//1 2663//1
+f 247//1 246//1 2663//1
+f 2663//1 246//1 2664//1
+f 246//1 245//1 2664//1
+f 2664//1 245//1 2665//1
+f 245//1 244//1 2665//1
+f 2665//1 244//1 2666//1
+f 244//1 243//1 2666//1
+f 2666//1 243//1 2667//1
+f 243//1 242//1 2667//1
+f 2667//1 242//1 2668//1
+f 242//1 241//1 2668//1
+f 2668//1 241//1 2669//1
+f 241//1 240//1 2669//1
+f 2669//1 240//1 2670//1
+f 240//1 239//1 2670//1
+f 2670//1 239//1 2671//1
+f 239//1 238//1 2671//1
+f 2671//1 238//1 2672//1
+f 238//1 237//1 2672//1
+f 2672//1 237//1 2673//1
+f 237//1 236//1 2673//1
+f 2673//1 236//1 2674//1
+f 236//1 235//1 2674//1
+f 2674//1 235//1 2675//1
+f 235//1 234//1 2675//1
+f 2675//1 234//1 2676//1
+f 234//1 233//1 2676//1
+f 2676//1 233//1 2677//1
+f 233//1 232//1 2677//1
+f 2677//1 232//1 2678//1
+f 232//1 231//1 2678//1
+f 2678//1 231//1 2679//1
+f 231//1 230//1 2679//1
+f 2679//1 230//1 2680//1
+f 230//1 229//1 2680//1
+f 2680//1 229//1 2681//1
+f 229//1 228//1 2681//1
+f 2681//1 228//1 2682//1
+f 228//1 227//1 2682//1
+f 2682//1 227//1 2683//1
+f 227//1 226//1 2683//1
+f 2683//1 226//1 2684//1
+f 226//1 225//1 2684//1
+f 2684//1 225//1 2685//1
+f 225//1 224//1 2685//1
+f 2685//1 224//1 2686//1
+f 224//1 223//1 2686//1
+f 2686//1 223//1 2687//1
+f 223//1 222//1 2687//1
+f 2687//1 222//1 2688//1
+f 222//1 221//1 2688//1
+f 2688//1 221//1 2689//1
+f 221//1 220//1 2689//1
+f 2689//1 220//1 2690//1
+f 220//1 219//1 2690//1
+f 2690//1 219//1 2691//1
+f 219//1 218//1 2691//1
+f 2691//1 218//1 2692//1
+f 218//1 217//1 2692//1
+f 2692//1 217//1 2693//1
+f 217//1 216//1 2693//1
+f 2693//1 216//1 2694//1
+f 216//1 215//1 2694//1
+f 2694//1 215//1 2695//1
+f 215//1 214//1 2695//1
+f 2695//1 214//1 2696//1
+f 214//1 213//1 2696//1
+f 2696//1 213//1 2697//1
+f 213//1 212//1 2697//1
+f 2697//1 212//1 2698//1
+f 212//1 211//1 2698//1
+f 2698//1 211//1 2699//1
+f 211//1 210//1 2699//1
+f 2699//1 210//1 2700//1
+f 210//1 209//1 2700//1
+f 2700//1 209//1 2701//1
+f 209//1 208//1 2701//1
+f 2701//1 208//1 2702//1
+f 208//1 207//1 2702//1
+f 2702//1 207//1 2703//1
+f 207//1 206//1 2703//1
+f 2703//1 206//1 2704//1
+f 206//1 205//1 2704//1
+f 2704//1 205//1 5//1
+f 205//1 3//1 5//1
+o Torus
+v 1.269537 0.006289 1.359776
+v 1.258843 0.006289 1.196618
+v 1.225636 0.131289 1.200990
+v 1.236043 0.131289 1.359776
+v 1.134912 0.222796 1.212934
+v 1.144537 0.222796 1.359776
+v 1.010982 0.256289 1.229250
+v 1.019537 0.256289 1.359776
+v 0.887051 0.222796 1.245565
+v 0.894537 0.222796 1.359776
+v 0.796328 0.131289 1.257509
+v 0.803031 0.131289 1.359776
+v 0.763121 0.006289 1.261881
+v 0.769537 0.006289 1.359776
+v 0.796328 -0.118711 1.257509
+v 0.803031 -0.118711 1.359776
+v 0.887051 -0.210217 1.245565
+v 0.894537 -0.210217 1.359776
+v 1.010982 -0.243711 1.229250
+v 1.019537 -0.243711 1.359776
+v 1.134912 -0.210217 1.212934
+v 1.144537 -0.210217 1.359776
+v 1.225636 -0.118711 1.200990
+v 1.236043 -0.118711 1.359776
+v 1.226944 0.006289 1.036252
+v 1.194592 0.131289 1.044921
+v 1.106204 0.222796 1.068604
+v 0.985463 0.256289 1.100957
+v 0.864722 0.222796 1.133309
+v 0.776334 0.131289 1.156993
+v 0.743981 0.006289 1.165661
+v 0.776334 -0.118711 1.156993
+v 0.864722 -0.210217 1.133309
+v 0.985463 -0.243711 1.100957
+v 1.106204 -0.210217 1.068604
+v 1.194592 -0.118711 1.044921
+v 1.174387 0.006289 0.881421
+v 1.143442 0.131289 0.894239
+v 1.058902 0.222796 0.929257
+v 0.943417 0.256289 0.977092
+v 0.827932 0.222796 1.024928
+v 0.743391 0.131289 1.059946
+v 0.712447 0.006289 1.072763
+v 0.743391 -0.118711 1.059946
+v 0.827932 -0.210217 1.024928
+v 0.943417 -0.243711 0.977092
+v 1.058902 -0.210217 0.929257
+v 1.143442 -0.118711 0.894239
+v 1.102069 0.006289 0.734776
+v 1.073062 0.131289 0.751522
+v 0.993815 0.222796 0.797276
+v 0.885562 0.256289 0.859776
+v 0.777309 0.222796 0.922276
+v 0.698062 0.131289 0.968029
+v 0.669056 0.006289 0.984776
+v 0.698062 -0.118711 0.968029
+v 0.777309 -0.210217 0.922276
+v 0.885562 -0.243711 0.859776
+v 0.993815 -0.210217 0.797276
+v 1.073062 -0.118711 0.751522
+v 1.011229 0.006289 0.598824
+v 0.984656 0.131289 0.619214
+v 0.912059 0.222796 0.674919
+v 0.812890 0.256289 0.751014
+v 0.713721 0.222796 0.827109
+v 0.641124 0.131289 0.882815
+v 0.614552 0.006289 0.903205
+v 0.641124 -0.118711 0.882815
+v 0.713721 -0.210217 0.827109
+v 0.812890 -0.243711 0.751014
+v 0.912059 -0.210217 0.674919
+v 0.984656 -0.118711 0.619214
+v 0.903420 0.006289 0.475892
+v 0.879737 0.131289 0.499576
+v 0.815032 0.222796 0.564281
+v 0.726644 0.256289 0.652669
+v 0.638255 0.222796 0.741057
+v 0.573551 0.131289 0.805762
+v 0.549867 0.006289 0.829446
+v 0.573551 -0.118711 0.805762
+v 0.638255 -0.210217 0.741057
+v 0.726644 -0.243711 0.652669
+v 0.815032 -0.210217 0.564281
+v 0.879737 -0.118711 0.499576
+v 0.780489 0.006289 0.368084
+v 0.760099 0.131289 0.394656
+v 0.704394 0.222796 0.467253
+v 0.628298 0.256289 0.566423
+v 0.552203 0.222796 0.665592
+v 0.496498 0.131289 0.738188
+v 0.476108 0.006289 0.764761
+v 0.496498 -0.118711 0.738188
+v 0.552203 -0.210217 0.665592
+v 0.628298 -0.243711 0.566423
+v 0.704394 -0.210217 0.467253
+v 0.760099 -0.118711 0.394656
+v 0.644537 0.006289 0.277244
+v 0.627790 0.131289 0.306250
+v 0.582037 0.222796 0.385497
+v 0.519537 0.256289 0.493750
+v 0.457037 0.222796 0.602003
+v 0.411284 0.131289 0.681250
+v 0.394537 0.006289 0.710257
+v 0.411284 -0.118711 0.681250
+v 0.457037 -0.210217 0.602003
+v 0.519537 -0.243711 0.493750
+v 0.582037 -0.210217 0.385497
+v 0.627790 -0.118711 0.306250
+v 0.497891 0.006289 0.204926
+v 0.485074 0.131289 0.235871
+v 0.450056 0.222796 0.320411
+v 0.402221 0.256289 0.435896
+v 0.354385 0.222796 0.551381
+v 0.319367 0.131289 0.635922
+v 0.306550 0.006289 0.666866
+v 0.319367 -0.118711 0.635922
+v 0.354385 -0.210217 0.551381
+v 0.402221 -0.243711 0.435896
+v 0.450056 -0.210217 0.320411
+v 0.485074 -0.118711 0.235871
+v 0.343061 0.006289 0.152368
+v 0.334392 0.131289 0.184721
+v 0.310708 0.222796 0.273109
+v 0.278356 0.256289 0.393850
+v 0.246004 0.222796 0.514591
+v 0.222320 0.131289 0.602979
+v 0.213651 0.006289 0.635331
+v 0.222320 -0.118711 0.602979
+v 0.246004 -0.210217 0.514591
+v 0.278356 -0.243711 0.393850
+v 0.310708 -0.210217 0.273109
+v 0.334392 -0.118711 0.184721
+v 0.182694 0.006289 0.120470
+v 0.178323 0.131289 0.153677
+v 0.166379 0.222796 0.244400
+v 0.150063 0.256289 0.368331
+v 0.133747 0.222796 0.492261
+v 0.121803 0.131289 0.582985
+v 0.117431 0.006289 0.616192
+v 0.121803 -0.118711 0.582985
+v 0.133747 -0.210217 0.492261
+v 0.150063 -0.243711 0.368331
+v 0.166379 -0.210217 0.244400
+v 0.178323 -0.118711 0.153677
+v 0.019537 0.006289 0.109776
+v 0.019537 0.131289 0.143269
+v 0.019537 0.222796 0.234776
+v 0.019537 0.256289 0.359776
+v 0.019537 0.222796 0.484776
+v 0.019537 0.131289 0.576282
+v 0.019537 0.006289 0.609776
+v 0.019537 -0.118711 0.576282
+v 0.019537 -0.210217 0.484776
+v 0.019537 -0.243711 0.359776
+v 0.019537 -0.210217 0.234776
+v 0.019537 -0.118711 0.143269
+v -0.143621 0.006289 0.120470
+v -0.139249 0.131289 0.153677
+v -0.127305 0.222796 0.244400
+v -0.110989 0.256289 0.368331
+v -0.094674 0.222796 0.492261
+v -0.082730 0.131289 0.582985
+v -0.078358 0.006289 0.616192
+v -0.082730 -0.118711 0.582985
+v -0.094674 -0.210217 0.492261
+v -0.110989 -0.243711 0.368331
+v -0.127305 -0.210217 0.244400
+v -0.139249 -0.118711 0.153677
+v -0.303987 0.006289 0.152368
+v -0.295318 0.131289 0.184721
+v -0.271634 0.222796 0.273109
+v -0.239282 0.256289 0.393850
+v -0.206930 0.222796 0.514590
+v -0.183246 0.131289 0.602979
+v -0.174577 0.006289 0.635331
+v -0.183246 -0.118711 0.602979
+v -0.206930 -0.210217 0.514590
+v -0.239282 -0.243711 0.393850
+v -0.271634 -0.210217 0.273109
+v -0.295318 -0.118711 0.184721
+v -0.458818 0.006289 0.204926
+v -0.446000 0.131289 0.235870
+v -0.410982 0.222796 0.320411
+v -0.363147 0.256289 0.435896
+v -0.315311 0.222796 0.551381
+v -0.280293 0.131289 0.635922
+v -0.267476 0.006289 0.666866
+v -0.280293 -0.118711 0.635922
+v -0.315311 -0.210217 0.551381
+v -0.363147 -0.243711 0.435896
+v -0.410982 -0.210217 0.320411
+v -0.446000 -0.118711 0.235870
+v -0.605463 0.006289 0.277244
+v -0.588716 0.131289 0.306250
+v -0.542963 0.222796 0.385497
+v -0.480463 0.256289 0.493750
+v -0.417963 0.222796 0.602003
+v -0.372210 0.131289 0.681250
+v -0.355463 0.006289 0.710257
+v -0.372210 -0.118711 0.681250
+v -0.417963 -0.210217 0.602003
+v -0.480463 -0.243711 0.493750
+v -0.542963 -0.210217 0.385497
+v -0.588716 -0.118711 0.306250
+v -0.741415 0.006289 0.368084
+v -0.721025 0.131289 0.394656
+v -0.665320 0.222796 0.467253
+v -0.589225 0.256289 0.566422
+v -0.513129 0.222796 0.665592
+v -0.457424 0.131289 0.738188
+v -0.437034 0.006289 0.764761
+v -0.457424 -0.118711 0.738188
+v -0.513129 -0.210217 0.665592
+v -0.589225 -0.243711 0.566422
+v -0.665320 -0.210217 0.467253
+v -0.721025 -0.118711 0.394656
+v -0.864347 0.006289 0.475893
+v -0.840663 0.131289 0.499576
+v -0.775958 0.222796 0.564281
+v -0.687570 0.256289 0.652669
+v -0.599182 0.222796 0.741057
+v -0.534477 0.131289 0.805762
+v -0.510793 0.006289 0.829446
+v -0.534477 -0.118711 0.805762
+v -0.599182 -0.210217 0.741057
+v -0.687570 -0.243711 0.652669
+v -0.775958 -0.210217 0.564281
+v -0.840663 -0.118711 0.499576
+v -0.972155 0.006289 0.598824
+v -0.945583 0.131289 0.619214
+v -0.872986 0.222796 0.674919
+v -0.773816 0.256289 0.751014
+v -0.674647 0.222796 0.827109
+v -0.602050 0.131289 0.882815
+v -0.575478 0.006289 0.903205
+v -0.602050 -0.118711 0.882815
+v -0.674647 -0.210217 0.827109
+v -0.773816 -0.243711 0.751014
+v -0.872986 -0.210217 0.674919
+v -0.945583 -0.118711 0.619214
+v -1.062995 0.006289 0.734775
+v -1.033988 0.131289 0.751522
+v -0.954742 0.222796 0.797275
+v -0.846488 0.256289 0.859775
+v -0.738235 0.222796 0.922275
+v -0.658988 0.131289 0.968029
+v -0.629982 0.006289 0.984775
+v -0.658988 -0.118711 0.968029
+v -0.738235 -0.210217 0.922275
+v -0.846488 -0.243711 0.859775
+v -0.954742 -0.210217 0.797275
+v -1.033988 -0.118711 0.751522
+v -1.135312 0.006289 0.881421
+v -1.104368 0.131289 0.894239
+v -1.019827 0.222796 0.929257
+v -0.904343 0.256289 0.977092
+v -0.788858 0.222796 1.024928
+v -0.704317 0.131289 1.059946
+v -0.673373 0.006289 1.072763
+v -0.704317 -0.118711 1.059946
+v -0.788858 -0.210217 1.024928
+v -0.904343 -0.243711 0.977092
+v -1.019827 -0.210217 0.929257
+v -1.104368 -0.118711 0.894239
+v -1.187871 0.006289 1.036252
+v -1.155518 0.131289 1.044921
+v -1.067130 0.222796 1.068604
+v -0.946389 0.256289 1.100957
+v -0.825648 0.222796 1.133309
+v -0.737260 0.131289 1.156993
+v -0.704908 0.006289 1.165662
+v -0.737260 -0.118711 1.156993
+v -0.825648 -0.210217 1.133309
+v -0.946389 -0.243711 1.100957
+v -1.067130 -0.210217 1.068604
+v -1.155518 -0.118711 1.044921
+v -1.219769 0.006289 1.196618
+v -1.186562 0.131289 1.200990
+v -1.095839 0.222796 1.212934
+v -0.971908 0.256289 1.229249
+v -0.847977 0.222796 1.245565
+v -0.757254 0.131289 1.257509
+v -0.724047 0.006289 1.261881
+v -0.757254 -0.118711 1.257509
+v -0.847977 -0.210217 1.245565
+v -0.971908 -0.243711 1.229249
+v -1.095839 -0.210217 1.212934
+v -1.186562 -0.118711 1.200990
+v -1.230463 0.006289 1.359776
+v -1.196970 0.131289 1.359776
+v -1.105463 0.222796 1.359776
+v -0.980463 0.256289 1.359776
+v -0.855463 0.222796 1.359776
+v -0.763957 0.131289 1.359776
+v -0.730463 0.006289 1.359776
+v -0.763957 -0.118711 1.359776
+v -0.855463 -0.210217 1.359776
+v -0.980463 -0.243711 1.359776
+v -1.105463 -0.210217 1.359776
+v -1.196970 -0.118711 1.359776
+v -1.219769 0.006289 1.522934
+v -1.186562 0.131289 1.518562
+v -1.095839 0.222796 1.506618
+v -0.971908 0.256289 1.490302
+v -0.847977 0.222796 1.473986
+v -0.757254 0.131289 1.462042
+v -0.724047 0.006289 1.457670
+v -0.757254 -0.118711 1.462042
+v -0.847977 -0.210217 1.473986
+v -0.971908 -0.243711 1.490302
+v -1.095839 -0.210217 1.506618
+v -1.186562 -0.118711 1.518562
+v -1.187871 0.006289 1.683299
+v -1.155518 0.131289 1.674631
+v -1.067130 0.222796 1.650947
+v -0.946389 0.256289 1.618595
+v -0.825648 0.222796 1.586242
+v -0.737260 0.131289 1.562559
+v -0.704908 0.006289 1.553890
+v -0.737260 -0.118711 1.562559
+v -0.825648 -0.210217 1.586242
+v -0.946389 -0.243711 1.618595
+v -1.067130 -0.210217 1.650947
+v -1.155518 -0.118711 1.674631
+v -1.135313 0.006289 1.838130
+v -1.104369 0.131289 1.825312
+v -1.019828 0.222796 1.790294
+v -0.904343 0.256289 1.742459
+v -0.788858 0.222796 1.694623
+v -0.704317 0.131289 1.659605
+v -0.673373 0.006289 1.646788
+v -0.704317 -0.118711 1.659605
+v -0.788858 -0.210217 1.694623
+v -0.904343 -0.243711 1.742459
+v -1.019828 -0.210217 1.790294
+v -1.104369 -0.118711 1.825312
+v -1.062995 0.006289 1.984776
+v -1.033989 0.131289 1.968029
+v -0.954742 0.222796 1.922276
+v -0.846489 0.256289 1.859776
+v -0.738235 0.222796 1.797276
+v -0.658989 0.131289 1.751522
+v -0.629982 0.006289 1.734776
+v -0.658989 -0.118711 1.751522
+v -0.738235 -0.210217 1.797276
+v -0.846489 -0.243711 1.859776
+v -0.954742 -0.210217 1.922276
+v -1.033989 -0.118711 1.968029
+v -0.972155 0.006289 2.120728
+v -0.945583 0.131289 2.100338
+v -0.872986 0.222796 2.044632
+v -0.773816 0.256289 1.968537
+v -0.674647 0.222796 1.892442
+v -0.602050 0.131289 1.836736
+v -0.575478 0.006289 1.816347
+v -0.602050 -0.118711 1.836736
+v -0.674647 -0.210217 1.892442
+v -0.773816 -0.243711 1.968537
+v -0.872986 -0.210217 2.044632
+v -0.945583 -0.118711 2.100338
+v -0.864347 0.006289 2.243659
+v -0.840663 0.131289 2.219975
+v -0.775958 0.222796 2.155271
+v -0.687570 0.256289 2.066882
+v -0.599182 0.222796 1.978494
+v -0.534477 0.131289 1.913789
+v -0.510793 0.006289 1.890106
+v -0.534477 -0.118711 1.913789
+v -0.599182 -0.210217 1.978494
+v -0.687570 -0.243711 2.066882
+v -0.775958 -0.210217 2.155271
+v -0.840663 -0.118711 2.219975
+v -0.741416 0.006289 2.351467
+v -0.721026 0.131289 2.324895
+v -0.665320 0.222796 2.252298
+v -0.589225 0.256289 2.153129
+v -0.513130 0.222796 2.053960
+v -0.457424 0.131289 1.981363
+v -0.437034 0.006289 1.954791
+v -0.457424 -0.118711 1.981363
+v -0.513130 -0.210217 2.053960
+v -0.589225 -0.243711 2.153129
+v -0.665320 -0.210217 2.252298
+v -0.721026 -0.118711 2.324895
+v -0.605463 0.006289 2.442308
+v -0.588716 0.131289 2.413301
+v -0.542963 0.222796 2.334054
+v -0.480463 0.256289 2.225801
+v -0.417963 0.222796 2.117548
+v -0.372210 0.131289 2.038301
+v -0.355463 0.006289 2.009295
+v -0.372210 -0.118711 2.038301
+v -0.417963 -0.210217 2.117548
+v -0.480463 -0.243711 2.225801
+v -0.542963 -0.210217 2.334054
+v -0.588716 -0.118711 2.413301
+v -0.458818 0.006289 2.514625
+v -0.446000 0.131289 2.483681
+v -0.410982 0.222796 2.399140
+v -0.363147 0.256289 2.283655
+v -0.315311 0.222796 2.168170
+v -0.280293 0.131289 2.083629
+v -0.267476 0.006289 2.052685
+v -0.280293 -0.118711 2.083629
+v -0.315311 -0.210217 2.168170
+v -0.363147 -0.243711 2.283655
+v -0.410982 -0.210217 2.399140
+v -0.446000 -0.118711 2.483681
+v -0.303987 0.006289 2.567183
+v -0.295318 0.131289 2.534830
+v -0.271635 0.222796 2.446442
+v -0.239282 0.256289 2.325701
+v -0.206930 0.222796 2.204961
+v -0.183246 0.131289 2.116572
+v -0.174578 0.006289 2.084220
+v -0.183246 -0.118711 2.116572
+v -0.206930 -0.210217 2.204961
+v -0.239282 -0.243711 2.325701
+v -0.271635 -0.210217 2.446442
+v -0.295318 -0.118711 2.534830
+v -0.143622 0.006289 2.599082
+v -0.139250 0.131289 2.565874
+v -0.127306 0.222796 2.475151
+v -0.110990 0.256289 2.351220
+v -0.094674 0.222796 2.227290
+v -0.082730 0.131289 2.136566
+v -0.078358 0.006289 2.103359
+v -0.082730 -0.118711 2.136566
+v -0.094674 -0.210217 2.227290
+v -0.110990 -0.243711 2.351220
+v -0.127306 -0.210217 2.475151
+v -0.139250 -0.118711 2.565874
+v 0.019537 0.006289 2.609776
+v 0.019537 0.131289 2.576282
+v 0.019537 0.222796 2.484776
+v 0.019537 0.256289 2.359776
+v 0.019537 0.222796 2.234776
+v 0.019537 0.131289 2.143269
+v 0.019537 0.006289 2.109776
+v 0.019537 -0.118711 2.143269
+v 0.019537 -0.210217 2.234776
+v 0.019537 -0.243711 2.359776
+v 0.019537 -0.210217 2.484776
+v 0.019537 -0.118711 2.576282
+v 0.182694 0.006289 2.599082
+v 0.178323 0.131289 2.565875
+v 0.166379 0.222796 2.475151
+v 0.150063 0.256289 2.351221
+v 0.133747 0.222796 2.227290
+v 0.121803 0.131289 2.136566
+v 0.117431 0.006289 2.103359
+v 0.121803 -0.118711 2.136566
+v 0.133747 -0.210217 2.227290
+v 0.150063 -0.243711 2.351221
+v 0.166379 -0.210217 2.475151
+v 0.178323 -0.118711 2.565875
+v 0.343060 0.006289 2.567183
+v 0.334391 0.131289 2.534831
+v 0.310708 0.222796 2.446442
+v 0.278356 0.256289 2.325702
+v 0.246003 0.222796 2.204961
+v 0.222320 0.131289 2.116573
+v 0.213651 0.006289 2.084220
+v 0.222320 -0.118711 2.116573
+v 0.246003 -0.210217 2.204961
+v 0.278356 -0.243711 2.325702
+v 0.310708 -0.210217 2.446442
+v 0.334391 -0.118711 2.534831
+v 0.497891 0.006289 2.514625
+v 0.485074 0.131289 2.483681
+v 0.450056 0.222796 2.399140
+v 0.402221 0.256289 2.283655
+v 0.354385 0.222796 2.168170
+v 0.319367 0.131289 2.083629
+v 0.306550 0.006289 2.052685
+v 0.319367 -0.118711 2.083629
+v 0.354385 -0.210217 2.168170
+v 0.402221 -0.243711 2.283655
+v 0.450056 -0.210217 2.399140
+v 0.485074 -0.118711 2.483681
+v 0.644537 0.006289 2.442307
+v 0.627790 0.131289 2.413301
+v 0.582037 0.222796 2.334054
+v 0.519537 0.256289 2.225801
+v 0.457037 0.222796 2.117548
+v 0.411284 0.131289 2.038301
+v 0.394537 0.006289 2.009295
+v 0.411284 -0.118711 2.038301
+v 0.457037 -0.210217 2.117548
+v 0.519537 -0.243711 2.225801
+v 0.582037 -0.210217 2.334054
+v 0.627790 -0.118711 2.413301
+v 0.780488 0.006289 2.351468
+v 0.760099 0.131289 2.324895
+v 0.704393 0.222796 2.252298
+v 0.628298 0.256289 2.153129
+v 0.552203 0.222796 2.053960
+v 0.496497 0.131289 1.981363
+v 0.476108 0.006289 1.954791
+v 0.496497 -0.118711 1.981363
+v 0.552203 -0.210217 2.053960
+v 0.628298 -0.243711 2.153129
+v 0.704393 -0.210217 2.252298
+v 0.760099 -0.118711 2.324895
+v 0.903420 0.006289 2.243660
+v 0.879736 0.131289 2.219976
+v 0.815032 0.222796 2.155271
+v 0.726643 0.256289 2.066883
+v 0.638255 0.222796 1.978495
+v 0.573550 0.131289 1.913790
+v 0.549867 0.006289 1.890106
+v 0.573550 -0.118711 1.913790
+v 0.638255 -0.210217 1.978495
+v 0.726643 -0.243711 2.066883
+v 0.815032 -0.210217 2.155271
+v 0.879736 -0.118711 2.219976
+v 1.011229 0.006289 2.120727
+v 0.984656 0.131289 2.100338
+v 0.912059 0.222796 2.044632
+v 0.812890 0.256289 1.968537
+v 0.713721 0.222796 1.892442
+v 0.641124 0.131289 1.836736
+v 0.614552 0.006289 1.816347
+v 0.641124 -0.118711 1.836736
+v 0.713721 -0.210217 1.892442
+v 0.812890 -0.243711 1.968537
+v 0.912059 -0.210217 2.044632
+v 0.984656 -0.118711 2.100338
+v 1.102069 0.006289 1.984776
+v 1.073062 0.131289 1.968029
+v 0.993815 0.222796 1.922276
+v 0.885562 0.256289 1.859776
+v 0.777309 0.222796 1.797276
+v 0.698062 0.131289 1.751523
+v 0.669056 0.006289 1.734776
+v 0.698062 -0.118711 1.751523
+v 0.777309 -0.210217 1.797276
+v 0.885562 -0.243711 1.859776
+v 0.993815 -0.210217 1.922276
+v 1.073062 -0.118711 1.968029
+v 1.174386 0.006289 1.838130
+v 1.143442 0.131289 1.825313
+v 1.058901 0.222796 1.790295
+v 0.943416 0.256289 1.742460
+v 0.827931 0.222796 1.694624
+v 0.743391 0.131289 1.659606
+v 0.712446 0.006289 1.646789
+v 0.743391 -0.118711 1.659606
+v 0.827931 -0.210217 1.694624
+v 0.943416 -0.243711 1.742460
+v 1.058901 -0.210217 1.790295
+v 1.143442 -0.118711 1.825313
+v 1.226944 0.006289 1.683299
+v 1.194592 0.131289 1.674630
+v 1.106204 0.222796 1.650947
+v 0.985463 0.256289 1.618594
+v 0.864722 0.222796 1.586242
+v 0.776334 0.131289 1.562559
+v 0.743981 0.006289 1.553890
+v 0.776334 -0.118711 1.562559
+v 0.864722 -0.210217 1.586242
+v 0.985463 -0.243711 1.618594
+v 1.106204 -0.210217 1.650947
+v 1.194592 -0.118711 1.674630
+v 1.258843 0.006289 1.522933
+v 1.225636 0.131289 1.518562
+v 1.134912 0.222796 1.506618
+v 1.010982 0.256289 1.490302
+v 0.887051 0.222796 1.473986
+v 0.796328 0.131289 1.462042
+v 0.763121 0.006289 1.457670
+v 0.796328 -0.118711 1.462042
+v 0.887051 -0.210217 1.473986
+v 1.010982 -0.243711 1.490302
+v 1.134912 -0.210217 1.506618
+v 1.225636 -0.118711 1.518562
+vn 0.9640 0.2583 -0.0632
+vn 0.7064 0.7063 -0.0463
+vn 0.2588 0.9658 -0.0170
+vn -0.2588 0.9658 0.0170
+vn -0.7064 0.7063 0.0463
+vn -0.9640 0.2583 0.0632
+vn -0.9640 -0.2583 0.0632
+vn -0.7063 -0.7063 0.0463
+vn -0.2588 -0.9658 0.0170
+vn 0.2588 -0.9658 -0.0170
+vn 0.7063 -0.7064 -0.0463
+vn 0.9640 -0.2583 -0.0632
+vn 0.9475 0.2583 -0.1885
+vn 0.6943 0.7063 -0.1381
+vn 0.2543 0.9658 -0.0506
+vn -0.2543 0.9658 0.0506
+vn -0.6943 0.7063 0.1381
+vn -0.9475 0.2583 0.1885
+vn -0.9475 -0.2583 0.1885
+vn -0.6943 -0.7063 0.1381
+vn -0.2544 -0.9658 0.0506
+vn 0.2544 -0.9658 -0.0506
+vn 0.6943 -0.7063 -0.1381
+vn 0.9475 -0.2583 -0.1885
+vn 0.9148 0.2583 -0.3105
+vn 0.6703 0.7063 -0.2275
+vn 0.2456 0.9658 -0.0834
+vn -0.2456 0.9658 0.0834
+vn -0.6703 0.7063 0.2275
+vn -0.9148 0.2583 0.3105
+vn -0.9148 -0.2583 0.3105
+vn -0.6703 -0.7064 0.2275
+vn -0.2456 -0.9658 0.0834
+vn 0.2456 -0.9658 -0.0834
+vn 0.6703 -0.7063 -0.2275
+vn 0.9148 -0.2583 -0.3105
+vn 0.8664 0.2583 -0.4273
+vn 0.6349 0.7063 -0.3131
+vn 0.2326 0.9658 -0.1147
+vn -0.2326 0.9658 0.1147
+vn -0.6349 0.7063 0.3131
+vn -0.8664 0.2583 0.4273
+vn -0.8664 -0.2583 0.4273
+vn -0.6349 -0.7064 0.3131
+vn -0.2326 -0.9658 0.1147
+vn 0.2326 -0.9658 -0.1147
+vn 0.6349 -0.7064 -0.3131
+vn 0.8664 -0.2583 -0.4273
+vn 0.8033 0.2583 -0.5367
+vn 0.5886 0.7063 -0.3933
+vn 0.2156 0.9658 -0.1441
+vn -0.2156 0.9658 0.1441
+vn -0.5886 0.7063 0.3933
+vn -0.8033 0.2583 0.5367
+vn -0.8033 -0.2583 0.5367
+vn -0.5886 -0.7064 0.3933
+vn -0.2156 -0.9658 0.1441
+vn 0.2156 -0.9658 -0.1441
+vn 0.5886 -0.7063 -0.3933
+vn 0.8033 -0.2583 -0.5367
+vn 0.7263 0.2583 -0.6370
+vn 0.5322 0.7063 -0.4667
+vn 0.1950 0.9658 -0.1710
+vn -0.1950 0.9658 0.1710
+vn -0.5322 0.7063 0.4667
+vn -0.7263 0.2583 0.6370
+vn -0.7263 -0.2583 0.6370
+vn -0.5322 -0.7064 0.4667
+vn -0.1950 -0.9658 0.1710
+vn 0.1950 -0.9658 -0.1710
+vn 0.5322 -0.7063 -0.4667
+vn 0.7263 -0.2583 -0.6370
+vn 0.6370 0.2583 -0.7263
+vn 0.4667 0.7063 -0.5322
+vn 0.1710 0.9658 -0.1950
+vn -0.1710 0.9658 0.1950
+vn -0.4667 0.7063 0.5322
+vn -0.6370 0.2583 0.7263
+vn -0.6370 -0.2583 0.7263
+vn -0.4667 -0.7063 0.5322
+vn -0.1710 -0.9658 0.1950
+vn 0.1710 -0.9658 -0.1950
+vn 0.4667 -0.7064 -0.5322
+vn 0.6370 -0.2583 -0.7263
+vn 0.5367 0.2583 -0.8033
+vn 0.3933 0.7063 -0.5886
+vn 0.1441 0.9658 -0.2156
+vn -0.1441 0.9658 0.2156
+vn -0.3933 0.7063 0.5886
+vn -0.5367 0.2583 0.8033
+vn -0.5367 -0.2583 0.8033
+vn -0.3933 -0.7063 0.5886
+vn -0.1441 -0.9658 0.2156
+vn 0.1441 -0.9658 -0.2156
+vn 0.3933 -0.7063 -0.5886
+vn 0.5367 -0.2583 -0.8033
+vn 0.4273 0.2583 -0.8664
+vn 0.3131 0.7063 -0.6349
+vn 0.1147 0.9658 -0.2326
+vn -0.1147 0.9658 0.2326
+vn -0.3131 0.7063 0.6349
+vn -0.4273 0.2583 0.8664
+vn -0.4273 -0.2583 0.8664
+vn -0.3131 -0.7064 0.6349
+vn -0.1147 -0.9658 0.2326
+vn 0.1147 -0.9658 -0.2326
+vn 0.3131 -0.7063 -0.6349
+vn 0.4273 -0.2583 -0.8664
+vn 0.3105 0.2583 -0.9148
+vn 0.2275 0.7063 -0.6703
+vn 0.0834 0.9658 -0.2456
+vn -0.0834 0.9658 0.2456
+vn -0.2275 0.7063 0.6703
+vn -0.3105 0.2583 0.9148
+vn -0.3105 -0.2583 0.9148
+vn -0.2275 -0.7064 0.6703
+vn -0.0834 -0.9658 0.2456
+vn 0.0834 -0.9658 -0.2456
+vn 0.2275 -0.7063 -0.6703
+vn 0.3105 -0.2583 -0.9148
+vn 0.1885 0.2583 -0.9475
+vn 0.1381 0.7063 -0.6943
+vn 0.0506 0.9658 -0.2543
+vn -0.0506 0.9658 0.2543
+vn -0.1381 0.7063 0.6943
+vn -0.1885 0.2583 0.9475
+vn -0.1885 -0.2583 0.9475
+vn -0.1381 -0.7064 0.6943
+vn -0.0506 -0.9658 0.2544
+vn 0.0506 -0.9658 -0.2544
+vn 0.1381 -0.7063 -0.6943
+vn 0.1885 -0.2583 -0.9475
+vn 0.0632 0.2583 -0.9640
+vn 0.0463 0.7063 -0.7064
+vn 0.0170 0.9658 -0.2588
+vn -0.0170 0.9658 0.2588
+vn -0.0463 0.7063 0.7064
+vn -0.0632 0.2583 0.9640
+vn -0.0632 -0.2583 0.9640
+vn -0.0463 -0.7064 0.7063
+vn -0.0170 -0.9658 0.2588
+vn 0.0170 -0.9658 -0.2588
+vn 0.0463 -0.7064 -0.7063
+vn 0.0632 -0.2583 -0.9640
+vn -0.0632 0.2583 -0.9640
+vn -0.0463 0.7063 -0.7064
+vn -0.0170 0.9658 -0.2588
+vn 0.0170 0.9658 0.2588
+vn 0.0463 0.7063 0.7064
+vn 0.0632 0.2583 0.9640
+vn 0.0632 -0.2583 0.9640
+vn 0.0463 -0.7064 0.7063
+vn 0.0170 -0.9658 0.2588
+vn -0.0170 -0.9658 -0.2588
+vn -0.0463 -0.7064 -0.7063
+vn -0.0632 -0.2583 -0.9640
+vn -0.1885 0.2583 -0.9475
+vn -0.1381 0.7063 -0.6943
+vn -0.0506 0.9658 -0.2543
+vn 0.0506 0.9658 0.2544
+vn 0.1381 0.7063 0.6943
+vn 0.1885 0.2583 0.9475
+vn 0.1885 -0.2583 0.9475
+vn 0.1381 -0.7064 0.6943
+vn 0.0506 -0.9658 0.2544
+vn -0.0506 -0.9658 -0.2544
+vn -0.1381 -0.7063 -0.6943
+vn -0.1885 -0.2583 -0.9475
+vn -0.3105 0.2583 -0.9148
+vn -0.2275 0.7063 -0.6703
+vn -0.0834 0.9658 -0.2456
+vn 0.0834 0.9658 0.2456
+vn 0.2275 0.7063 0.6703
+vn 0.3105 0.2583 0.9148
+vn 0.3105 -0.2583 0.9148
+vn 0.2275 -0.7064 0.6703
+vn 0.0834 -0.9658 0.2456
+vn -0.0834 -0.9658 -0.2456
+vn -0.2275 -0.7063 -0.6703
+vn -0.3105 -0.2583 -0.9148
+vn -0.4273 0.2583 -0.8664
+vn -0.3131 0.7063 -0.6349
+vn -0.1147 0.9658 -0.2326
+vn 0.1147 0.9658 0.2326
+vn 0.3131 0.7063 0.6349
+vn 0.4273 0.2583 0.8664
+vn 0.4273 -0.2583 0.8664
+vn 0.3131 -0.7064 0.6349
+vn 0.1147 -0.9658 0.2326
+vn -0.1147 -0.9658 -0.2326
+vn -0.3131 -0.7064 -0.6349
+vn -0.4273 -0.2583 -0.8664
+vn -0.5367 0.2583 -0.8033
+vn -0.3933 0.7063 -0.5886
+vn -0.1441 0.9658 -0.2156
+vn 0.1441 0.9658 0.2156
+vn 0.3933 0.7063 0.5886
+vn 0.5367 0.2583 0.8033
+vn 0.5367 -0.2583 0.8033
+vn 0.3933 -0.7063 0.5886
+vn 0.1441 -0.9658 0.2156
+vn -0.1441 -0.9658 -0.2156
+vn -0.3933 -0.7063 -0.5886
+vn -0.5367 -0.2583 -0.8033
+vn -0.6370 0.2583 -0.7263
+vn -0.4667 0.7063 -0.5322
+vn -0.1710 0.9658 -0.1950
+vn 0.1710 0.9658 0.1950
+vn 0.4667 0.7063 0.5322
+vn 0.6370 0.2583 0.7263
+vn 0.6370 -0.2583 0.7263
+vn 0.4667 -0.7063 0.5322
+vn 0.1710 -0.9658 0.1950
+vn -0.1710 -0.9658 -0.1950
+vn -0.4667 -0.7063 -0.5322
+vn -0.6370 -0.2583 -0.7263
+vn -0.7263 0.2583 -0.6370
+vn -0.5322 0.7063 -0.4667
+vn -0.1950 0.9658 -0.1710
+vn 0.1950 0.9658 0.1710
+vn 0.5322 0.7063 0.4667
+vn 0.7263 0.2583 0.6370
+vn 0.7263 -0.2583 0.6370
+vn 0.5322 -0.7064 0.4667
+vn 0.1950 -0.9658 0.1710
+vn -0.1950 -0.9658 -0.1710
+vn -0.5322 -0.7063 -0.4667
+vn -0.7263 -0.2583 -0.6370
+vn -0.8033 0.2583 -0.5367
+vn -0.5886 0.7063 -0.3933
+vn -0.2156 0.9658 -0.1441
+vn 0.2156 0.9658 0.1441
+vn 0.5886 0.7063 0.3933
+vn 0.8033 0.2583 0.5367
+vn 0.8033 -0.2583 0.5367
+vn 0.5886 -0.7064 0.3933
+vn 0.2156 -0.9658 0.1441
+vn -0.2156 -0.9658 -0.1441
+vn -0.5886 -0.7063 -0.3933
+vn -0.8033 -0.2583 -0.5367
+vn -0.8664 0.2583 -0.4273
+vn -0.6349 0.7063 -0.3131
+vn -0.2326 0.9658 -0.1147
+vn 0.2326 0.9658 0.1147
+vn 0.6349 0.7063 0.3131
+vn 0.8664 0.2583 0.4273
+vn 0.8664 -0.2583 0.4273
+vn 0.6349 -0.7064 0.3131
+vn 0.2326 -0.9658 0.1147
+vn -0.2326 -0.9658 -0.1147
+vn -0.6349 -0.7063 -0.3131
+vn -0.8664 -0.2583 -0.4273
+vn -0.9148 0.2583 -0.3105
+vn -0.6703 0.7063 -0.2275
+vn -0.2456 0.9658 -0.0834
+vn 0.2456 0.9658 0.0834
+vn 0.6703 0.7063 0.2275
+vn 0.9148 0.2583 0.3105
+vn 0.9148 -0.2583 0.3105
+vn 0.6703 -0.7064 0.2275
+vn 0.2456 -0.9658 0.0834
+vn -0.2456 -0.9658 -0.0834
+vn -0.6703 -0.7063 -0.2275
+vn -0.9148 -0.2583 -0.3105
+vn -0.9475 0.2583 -0.1885
+vn -0.6943 0.7063 -0.1381
+vn -0.2543 0.9658 -0.0506
+vn 0.2543 0.9658 0.0506
+vn 0.6943 0.7063 0.1381
+vn 0.9475 0.2583 0.1885
+vn 0.9475 -0.2583 0.1885
+vn 0.6943 -0.7063 0.1381
+vn 0.2544 -0.9658 0.0506
+vn -0.2544 -0.9658 -0.0506
+vn -0.6943 -0.7063 -0.1381
+vn -0.9475 -0.2583 -0.1885
+vn -0.9640 0.2583 -0.0632
+vn -0.7064 0.7063 -0.0463
+vn -0.2588 0.9658 -0.0170
+vn 0.2588 0.9658 0.0170
+vn 0.7064 0.7063 0.0463
+vn 0.9640 0.2583 0.0632
+vn 0.9640 -0.2583 0.0632
+vn 0.7063 -0.7063 0.0463
+vn 0.2588 -0.9658 0.0170
+vn -0.2588 -0.9658 -0.0170
+vn -0.7063 -0.7064 -0.0463
+vn -0.9640 -0.2583 -0.0632
+vn 0.7063 -0.7063 -0.0463
+vn -0.7063 -0.7064 0.0463
+vn 0.6349 -0.7063 -0.3131
+vn 0.5886 -0.7064 -0.3933
+vn 0.5322 -0.7064 -0.4667
+vn -0.4667 -0.7064 0.5322
+vn 0.3933 -0.7064 -0.5886
+vn -0.3933 -0.7064 0.5886
+vn 0.3131 -0.7064 -0.6349
+vn 0.2275 -0.7064 -0.6703
+vn -0.2275 -0.7063 0.6703
+vn 0.0506 0.9658 -0.2544
+vn 0.1381 -0.7064 -0.6943
+vn -0.1381 -0.7063 0.6943
+vn 0.0463 0.7063 -0.7063
+vn -0.0463 -0.7063 0.7063
+vn -0.0463 0.7063 -0.7063
+vn -0.3933 -0.7064 -0.5886
+vn 0.3933 -0.7064 0.5886
+vn -0.4667 -0.7064 -0.5322
+vn 0.4667 -0.7064 0.5322
+vn -0.5322 -0.7064 -0.4667
+vn -0.5886 -0.7064 -0.3933
+vn 0.6703 -0.7063 0.2275
+vn 0.2544 0.9658 0.0506
+vn 0.6943 -0.7064 0.1381
+vn -0.7063 -0.7063 -0.0463
+vn 0.7063 -0.7064 0.0463
+usemtl None
+s 1
+f 2705//2 2706//2 2707//2 2708//2
+f 2708//3 2707//3 2709//3 2710//3
+f 2710//4 2709//4 2711//4 2712//4
+f 2712//5 2711//5 2713//5 2714//5
+f 2714//6 2713//6 2715//6 2716//6
+f 2716//7 2715//7 2717//7 2718//7
+f 2718//8 2717//8 2719//8 2720//8
+f 2720//9 2719//9 2721//9 2722//9
+f 2722//10 2721//10 2723//10 2724//10
+f 2724//11 2723//11 2725//11 2726//11
+f 2726//12 2725//12 2727//12 2728//12
+f 2705//13 2728//13 2727//13 2706//13
+f 2706//14 2729//14 2730//14 2707//14
+f 2707//15 2730//15 2731//15 2709//15
+f 2709//16 2731//16 2732//16 2711//16
+f 2711//17 2732//17 2733//17 2713//17
+f 2713//18 2733//18 2734//18 2715//18
+f 2715//19 2734//19 2735//19 2717//19
+f 2717//20 2735//20 2736//20 2719//20
+f 2719//21 2736//21 2737//21 2721//21
+f 2721//22 2737//22 2738//22 2723//22
+f 2723//23 2738//23 2739//23 2725//23
+f 2725//24 2739//24 2740//24 2727//24
+f 2727//25 2740//25 2729//25 2706//25
+f 2729//26 2741//26 2742//26 2730//26
+f 2730//27 2742//27 2743//27 2731//27
+f 2731//28 2743//28 2744//28 2732//28
+f 2732//29 2744//29 2745//29 2733//29
+f 2733//30 2745//30 2746//30 2734//30
+f 2734//31 2746//31 2747//31 2735//31
+f 2735//32 2747//32 2748//32 2736//32
+f 2736//33 2748//33 2749//33 2737//33
+f 2737//34 2749//34 2750//34 2738//34
+f 2738//35 2750//35 2751//35 2739//35
+f 2739//36 2751//36 2752//36 2740//36
+f 2740//37 2752//37 2741//37 2729//37
+f 2741//38 2753//38 2754//38 2742//38
+f 2742//39 2754//39 2755//39 2743//39
+f 2743//40 2755//40 2756//40 2744//40
+f 2744//41 2756//41 2757//41 2745//41
+f 2745//42 2757//42 2758//42 2746//42
+f 2746//43 2758//43 2759//43 2747//43
+f 2747//44 2759//44 2760//44 2748//44
+f 2748//45 2760//45 2761//45 2749//45
+f 2749//46 2761//46 2762//46 2750//46
+f 2750//47 2762//47 2763//47 2751//47
+f 2751//48 2763//48 2764//48 2752//48
+f 2752//49 2764//49 2753//49 2741//49
+f 2753//50 2765//50 2766//50 2754//50
+f 2754//51 2766//51 2767//51 2755//51
+f 2755//52 2767//52 2768//52 2756//52
+f 2756//53 2768//53 2769//53 2757//53
+f 2757//54 2769//54 2770//54 2758//54
+f 2758//55 2770//55 2771//55 2759//55
+f 2759//56 2771//56 2772//56 2760//56
+f 2760//57 2772//57 2773//57 2761//57
+f 2761//58 2773//58 2774//58 2762//58
+f 2762//59 2774//59 2775//59 2763//59
+f 2763//60 2775//60 2776//60 2764//60
+f 2764//61 2776//61 2765//61 2753//61
+f 2765//62 2777//62 2778//62 2766//62
+f 2766//63 2778//63 2779//63 2767//63
+f 2767//64 2779//64 2780//64 2768//64
+f 2768//65 2780//65 2781//65 2769//65
+f 2769//66 2781//66 2782//66 2770//66
+f 2770//67 2782//67 2783//67 2771//67
+f 2771//68 2783//68 2784//68 2772//68
+f 2772//69 2784//69 2785//69 2773//69
+f 2773//70 2785//70 2786//70 2774//70
+f 2774//71 2786//71 2787//71 2775//71
+f 2775//72 2787//72 2788//72 2776//72
+f 2776//73 2788//73 2777//73 2765//73
+f 2777//74 2789//74 2790//74 2778//74
+f 2778//75 2790//75 2791//75 2779//75
+f 2779//76 2791//76 2792//76 2780//76
+f 2780//77 2792//77 2793//77 2781//77
+f 2781//78 2793//78 2794//78 2782//78
+f 2782//79 2794//79 2795//79 2783//79
+f 2783//80 2795//80 2796//80 2784//80
+f 2784//81 2796//81 2797//81 2785//81
+f 2785//82 2797//82 2798//82 2786//82
+f 2786//83 2798//83 2799//83 2787//83
+f 2787//84 2799//84 2800//84 2788//84
+f 2788//85 2800//85 2789//85 2777//85
+f 2789//86 2801//86 2802//86 2790//86
+f 2790//87 2802//87 2803//87 2791//87
+f 2791//88 2803//88 2804//88 2792//88
+f 2792//89 2804//89 2805//89 2793//89
+f 2793//90 2805//90 2806//90 2794//90
+f 2794//91 2806//91 2807//91 2795//91
+f 2795//92 2807//92 2808//92 2796//92
+f 2796//93 2808//93 2809//93 2797//93
+f 2797//94 2809//94 2810//94 2798//94
+f 2798//95 2810//95 2811//95 2799//95
+f 2799//96 2811//96 2812//96 2800//96
+f 2800//97 2812//97 2801//97 2789//97
+f 2801//98 2813//98 2814//98 2802//98
+f 2802//99 2814//99 2815//99 2803//99
+f 2803//100 2815//100 2816//100 2804//100
+f 2804//101 2816//101 2817//101 2805//101
+f 2805//102 2817//102 2818//102 2806//102
+f 2806//103 2818//103 2819//103 2807//103
+f 2807//104 2819//104 2820//104 2808//104
+f 2808//105 2820//105 2821//105 2809//105
+f 2809//106 2821//106 2822//106 2810//106
+f 2810//107 2822//107 2823//107 2811//107
+f 2811//108 2823//108 2824//108 2812//108
+f 2812//109 2824//109 2813//109 2801//109
+f 2813//110 2825//110 2826//110 2814//110
+f 2814//111 2826//111 2827//111 2815//111
+f 2815//112 2827//112 2828//112 2816//112
+f 2816//113 2828//113 2829//113 2817//113
+f 2817//114 2829//114 2830//114 2818//114
+f 2818//115 2830//115 2831//115 2819//115
+f 2819//116 2831//116 2832//116 2820//116
+f 2820//117 2832//117 2833//117 2821//117
+f 2821//118 2833//118 2834//118 2822//118
+f 2822//119 2834//119 2835//119 2823//119
+f 2823//120 2835//120 2836//120 2824//120
+f 2824//121 2836//121 2825//121 2813//121
+f 2825//122 2837//122 2838//122 2826//122
+f 2826//123 2838//123 2839//123 2827//123
+f 2827//124 2839//124 2840//124 2828//124
+f 2828//125 2840//125 2841//125 2829//125
+f 2829//126 2841//126 2842//126 2830//126
+f 2830//127 2842//127 2843//127 2831//127
+f 2831//128 2843//128 2844//128 2832//128
+f 2832//129 2844//129 2845//129 2833//129
+f 2833//130 2845//130 2846//130 2834//130
+f 2834//131 2846//131 2847//131 2835//131
+f 2835//132 2847//132 2848//132 2836//132
+f 2836//133 2848//133 2837//133 2825//133
+f 2837//134 2849//134 2850//134 2838//134
+f 2838//135 2850//135 2851//135 2839//135
+f 2839//136 2851//136 2852//136 2840//136
+f 2840//137 2852//137 2853//137 2841//137
+f 2841//138 2853//138 2854//138 2842//138
+f 2842//139 2854//139 2855//139 2843//139
+f 2843//140 2855//140 2856//140 2844//140
+f 2844//141 2856//141 2857//141 2845//141
+f 2845//142 2857//142 2858//142 2846//142
+f 2846//143 2858//143 2859//143 2847//143
+f 2847//144 2859//144 2860//144 2848//144
+f 2848//145 2860//145 2849//145 2837//145
+f 2849//146 2861//146 2862//146 2850//146
+f 2850//147 2862//147 2863//147 2851//147
+f 2851//148 2863//148 2864//148 2852//148
+f 2852//149 2864//149 2865//149 2853//149
+f 2853//150 2865//150 2866//150 2854//150
+f 2854//151 2866//151 2867//151 2855//151
+f 2855//152 2867//152 2868//152 2856//152
+f 2856//153 2868//153 2869//153 2857//153
+f 2857//154 2869//154 2870//154 2858//154
+f 2858//155 2870//155 2871//155 2859//155
+f 2859//156 2871//156 2872//156 2860//156
+f 2860//157 2872//157 2861//157 2849//157
+f 2861//158 2873//158 2874//158 2862//158
+f 2862//159 2874//159 2875//159 2863//159
+f 2863//160 2875//160 2876//160 2864//160
+f 2864//161 2876//161 2877//161 2865//161
+f 2865//162 2877//162 2878//162 2866//162
+f 2866//163 2878//163 2879//163 2867//163
+f 2867//164 2879//164 2880//164 2868//164
+f 2868//165 2880//165 2881//165 2869//165
+f 2869//166 2881//166 2882//166 2870//166
+f 2870//167 2882//167 2883//167 2871//167
+f 2871//168 2883//168 2884//168 2872//168
+f 2872//169 2884//169 2873//169 2861//169
+f 2873//170 2885//170 2886//170 2874//170
+f 2874//171 2886//171 2887//171 2875//171
+f 2875//172 2887//172 2888//172 2876//172
+f 2876//173 2888//173 2889//173 2877//173
+f 2877//174 2889//174 2890//174 2878//174
+f 2878//175 2890//175 2891//175 2879//175
+f 2879//176 2891//176 2892//176 2880//176
+f 2880//177 2892//177 2893//177 2881//177
+f 2881//178 2893//178 2894//178 2882//178
+f 2882//179 2894//179 2895//179 2883//179
+f 2883//180 2895//180 2896//180 2884//180
+f 2884//181 2896//181 2885//181 2873//181
+f 2885//182 2897//182 2898//182 2886//182
+f 2886//183 2898//183 2899//183 2887//183
+f 2887//184 2899//184 2900//184 2888//184
+f 2888//185 2900//185 2901//185 2889//185
+f 2889//186 2901//186 2902//186 2890//186
+f 2890//187 2902//187 2903//187 2891//187
+f 2891//188 2903//188 2904//188 2892//188
+f 2892//189 2904//189 2905//189 2893//189
+f 2893//190 2905//190 2906//190 2894//190
+f 2894//191 2906//191 2907//191 2895//191
+f 2895//192 2907//192 2908//192 2896//192
+f 2896//193 2908//193 2897//193 2885//193
+f 2897//194 2909//194 2910//194 2898//194
+f 2898//195 2910//195 2911//195 2899//195
+f 2899//196 2911//196 2912//196 2900//196
+f 2900//197 2912//197 2913//197 2901//197
+f 2901//198 2913//198 2914//198 2902//198
+f 2902//199 2914//199 2915//199 2903//199
+f 2903//200 2915//200 2916//200 2904//200
+f 2904//201 2916//201 2917//201 2905//201
+f 2905//202 2917//202 2918//202 2906//202
+f 2906//203 2918//203 2919//203 2907//203
+f 2907//204 2919//204 2920//204 2908//204
+f 2908//205 2920//205 2909//205 2897//205
+f 2909//206 2921//206 2922//206 2910//206
+f 2910//207 2922//207 2923//207 2911//207
+f 2911//208 2923//208 2924//208 2912//208
+f 2912//209 2924//209 2925//209 2913//209
+f 2913//210 2925//210 2926//210 2914//210
+f 2914//211 2926//211 2927//211 2915//211
+f 2915//212 2927//212 2928//212 2916//212
+f 2916//213 2928//213 2929//213 2917//213
+f 2917//214 2929//214 2930//214 2918//214
+f 2918//215 2930//215 2931//215 2919//215
+f 2919//216 2931//216 2932//216 2920//216
+f 2920//217 2932//217 2921//217 2909//217
+f 2921//218 2933//218 2934//218 2922//218
+f 2922//219 2934//219 2935//219 2923//219
+f 2923//220 2935//220 2936//220 2924//220
+f 2924//221 2936//221 2937//221 2925//221
+f 2925//222 2937//222 2938//222 2926//222
+f 2926//223 2938//223 2939//223 2927//223
+f 2927//224 2939//224 2940//224 2928//224
+f 2928//225 2940//225 2941//225 2929//225
+f 2929//226 2941//226 2942//226 2930//226
+f 2930//227 2942//227 2943//227 2931//227
+f 2931//228 2943//228 2944//228 2932//228
+f 2932//229 2944//229 2933//229 2921//229
+f 2933//230 2945//230 2946//230 2934//230
+f 2934//231 2946//231 2947//231 2935//231
+f 2935//232 2947//232 2948//232 2936//232
+f 2936//233 2948//233 2949//233 2937//233
+f 2937//234 2949//234 2950//234 2938//234
+f 2938//235 2950//235 2951//235 2939//235
+f 2939//236 2951//236 2952//236 2940//236
+f 2940//237 2952//237 2953//237 2941//237
+f 2941//238 2953//238 2954//238 2942//238
+f 2942//239 2954//239 2955//239 2943//239
+f 2943//240 2955//240 2956//240 2944//240
+f 2944//241 2956//241 2945//241 2933//241
+f 2945//242 2957//242 2958//242 2946//242
+f 2946//243 2958//243 2959//243 2947//243
+f 2947//244 2959//244 2960//244 2948//244
+f 2948//245 2960//245 2961//245 2949//245
+f 2949//246 2961//246 2962//246 2950//246
+f 2950//247 2962//247 2963//247 2951//247
+f 2951//248 2963//248 2964//248 2952//248
+f 2952//249 2964//249 2965//249 2953//249
+f 2953//250 2965//250 2966//250 2954//250
+f 2954//251 2966//251 2967//251 2955//251
+f 2955//252 2967//252 2968//252 2956//252
+f 2956//253 2968//253 2957//253 2945//253
+f 2957//254 2969//254 2970//254 2958//254
+f 2958//255 2970//255 2971//255 2959//255
+f 2959//256 2971//256 2972//256 2960//256
+f 2960//257 2972//257 2973//257 2961//257
+f 2961//258 2973//258 2974//258 2962//258
+f 2962//259 2974//259 2975//259 2963//259
+f 2963//260 2975//260 2976//260 2964//260
+f 2964//261 2976//261 2977//261 2965//261
+f 2965//262 2977//262 2978//262 2966//262
+f 2966//263 2978//263 2979//263 2967//263
+f 2967//264 2979//264 2980//264 2968//264
+f 2968//265 2980//265 2969//265 2957//265
+f 2969//266 2981//266 2982//266 2970//266
+f 2970//267 2982//267 2983//267 2971//267
+f 2971//268 2983//268 2984//268 2972//268
+f 2972//269 2984//269 2985//269 2973//269
+f 2973//270 2985//270 2986//270 2974//270
+f 2974//271 2986//271 2987//271 2975//271
+f 2975//272 2987//272 2988//272 2976//272
+f 2976//273 2988//273 2989//273 2977//273
+f 2977//274 2989//274 2990//274 2978//274
+f 2978//275 2990//275 2991//275 2979//275
+f 2979//276 2991//276 2992//276 2980//276
+f 2980//277 2992//277 2981//277 2969//277
+f 2981//278 2993//278 2994//278 2982//278
+f 2982//279 2994//279 2995//279 2983//279
+f 2983//280 2995//280 2996//280 2984//280
+f 2984//281 2996//281 2997//281 2985//281
+f 2985//282 2997//282 2998//282 2986//282
+f 2986//283 2998//283 2999//283 2987//283
+f 2987//284 2999//284 3000//284 2988//284
+f 2988//285 3000//285 3001//285 2989//285
+f 2989//286 3001//286 3002//286 2990//286
+f 2990//287 3002//287 3003//287 2991//287
+f 2991//288 3003//288 3004//288 2992//288
+f 2992//289 3004//289 2993//289 2981//289
+f 2993//7 3005//7 3006//7 2994//7
+f 2994//6 3006//6 3007//6 2995//6
+f 2995//5 3007//5 3008//5 2996//5
+f 2996//4 3008//4 3009//4 2997//4
+f 2997//3 3009//3 3010//3 2998//3
+f 2998//2 3010//2 3011//2 2999//2
+f 2999//13 3011//13 3012//13 3000//13
+f 3000//290 3012//290 3013//290 3001//290
+f 3001//11 3013//11 3014//11 3002//11
+f 3002//10 3014//10 3015//10 3003//10
+f 3003//291 3015//291 3016//291 3004//291
+f 3004//8 3016//8 3005//8 2993//8
+f 3005//19 3017//19 3018//19 3006//19
+f 3006//18 3018//18 3019//18 3007//18
+f 3007//17 3019//17 3020//17 3008//17
+f 3008//16 3020//16 3021//16 3009//16
+f 3009//15 3021//15 3022//15 3010//15
+f 3010//14 3022//14 3023//14 3011//14
+f 3011//25 3023//25 3024//25 3012//25
+f 3012//24 3024//24 3025//24 3013//24
+f 3013//23 3025//23 3026//23 3014//23
+f 3014//22 3026//22 3027//22 3015//22
+f 3015//21 3027//21 3028//21 3016//21
+f 3016//20 3028//20 3017//20 3005//20
+f 3017//31 3029//31 3030//31 3018//31
+f 3018//30 3030//30 3031//30 3019//30
+f 3019//29 3031//29 3032//29 3020//29
+f 3020//28 3032//28 3033//28 3021//28
+f 3021//27 3033//27 3034//27 3022//27
+f 3022//26 3034//26 3035//26 3023//26
+f 3023//37 3035//37 3036//37 3024//37
+f 3024//36 3036//36 3037//36 3025//36
+f 3025//35 3037//35 3038//35 3026//35
+f 3026//34 3038//34 3039//34 3027//34
+f 3027//33 3039//33 3040//33 3028//33
+f 3028//32 3040//32 3029//32 3017//32
+f 3029//43 3041//43 3042//43 3030//43
+f 3030//42 3042//42 3043//42 3031//42
+f 3031//41 3043//41 3044//41 3032//41
+f 3032//40 3044//40 3045//40 3033//40
+f 3033//39 3045//39 3046//39 3034//39
+f 3034//38 3046//38 3047//38 3035//38
+f 3035//49 3047//49 3048//49 3036//49
+f 3036//292 3048//292 3049//292 3037//292
+f 3037//47 3049//47 3050//47 3038//47
+f 3038//46 3050//46 3051//46 3039//46
+f 3039//45 3051//45 3052//45 3040//45
+f 3040//44 3052//44 3041//44 3029//44
+f 3041//55 3053//55 3054//55 3042//55
+f 3042//54 3054//54 3055//54 3043//54
+f 3043//53 3055//53 3056//53 3044//53
+f 3044//52 3056//52 3057//52 3045//52
+f 3045//51 3057//51 3058//51 3046//51
+f 3046//50 3058//50 3059//50 3047//50
+f 3047//61 3059//61 3060//61 3048//61
+f 3048//293 3060//293 3061//293 3049//293
+f 3049//59 3061//59 3062//59 3050//59
+f 3050//58 3062//58 3063//58 3051//58
+f 3051//57 3063//57 3064//57 3052//57
+f 3052//56 3064//56 3053//56 3041//56
+f 3053//67 3065//67 3066//67 3054//67
+f 3054//66 3066//66 3067//66 3055//66
+f 3055//65 3067//65 3068//65 3056//65
+f 3056//64 3068//64 3069//64 3057//64
+f 3057//63 3069//63 3070//63 3058//63
+f 3058//62 3070//62 3071//62 3059//62
+f 3059//73 3071//73 3072//73 3060//73
+f 3060//294 3072//294 3073//294 3061//294
+f 3061//71 3073//71 3074//71 3062//71
+f 3062//70 3074//70 3075//70 3063//70
+f 3063//69 3075//69 3076//69 3064//69
+f 3064//68 3076//68 3065//68 3053//68
+f 3065//79 3077//79 3078//79 3066//79
+f 3066//78 3078//78 3079//78 3067//78
+f 3067//77 3079//77 3080//77 3068//77
+f 3068//76 3080//76 3081//76 3069//76
+f 3069//75 3081//75 3082//75 3070//75
+f 3070//74 3082//74 3083//74 3071//74
+f 3071//85 3083//85 3084//85 3072//85
+f 3072//84 3084//84 3085//84 3073//84
+f 3073//83 3085//83 3086//83 3074//83
+f 3074//82 3086//82 3087//82 3075//82
+f 3075//295 3087//295 3088//295 3076//295
+f 3076//80 3088//80 3077//80 3065//80
+f 3077//91 3089//91 3090//91 3078//91
+f 3078//90 3090//90 3091//90 3079//90
+f 3079//89 3091//89 3092//89 3080//89
+f 3080//88 3092//88 3093//88 3081//88
+f 3081//87 3093//87 3094//87 3082//87
+f 3082//86 3094//86 3095//86 3083//86
+f 3083//97 3095//97 3096//97 3084//97
+f 3084//296 3096//296 3097//296 3085//296
+f 3085//95 3097//95 3098//95 3086//95
+f 3086//94 3098//94 3099//94 3087//94
+f 3087//297 3099//297 3100//297 3088//297
+f 3088//92 3100//92 3089//92 3077//92
+f 3089//103 3101//103 3102//103 3090//103
+f 3090//102 3102//102 3103//102 3091//102
+f 3091//101 3103//101 3104//101 3092//101
+f 3092//100 3104//100 3105//100 3093//100
+f 3093//99 3105//99 3106//99 3094//99
+f 3094//98 3106//98 3107//98 3095//98
+f 3095//109 3107//109 3108//109 3096//109
+f 3096//298 3108//298 3109//298 3097//298
+f 3097//107 3109//107 3110//107 3098//107
+f 3098//106 3110//106 3111//106 3099//106
+f 3099//105 3111//105 3112//105 3100//105
+f 3100//104 3112//104 3101//104 3089//104
+f 3101//115 3113//115 3114//115 3102//115
+f 3102//114 3114//114 3115//114 3103//114
+f 3103//113 3115//113 3116//113 3104//113
+f 3104//112 3116//112 3117//112 3105//112
+f 3105//111 3117//111 3118//111 3106//111
+f 3106//110 3118//110 3119//110 3107//110
+f 3107//121 3119//121 3120//121 3108//121
+f 3108//299 3120//299 3121//299 3109//299
+f 3109//119 3121//119 3122//119 3110//119
+f 3110//118 3122//118 3123//118 3111//118
+f 3111//300 3123//300 3124//300 3112//300
+f 3112//116 3124//116 3113//116 3101//116
+f 3113//127 3125//127 3126//127 3114//127
+f 3114//126 3126//126 3127//126 3115//126
+f 3115//125 3127//125 3128//125 3116//125
+f 3116//301 3128//301 3129//301 3117//301
+f 3117//123 3129//123 3130//123 3118//123
+f 3118//122 3130//122 3131//122 3119//122
+f 3119//133 3131//133 3132//133 3120//133
+f 3120//302 3132//302 3133//302 3121//302
+f 3121//131 3133//131 3134//131 3122//131
+f 3122//130 3134//130 3135//130 3123//130
+f 3123//303 3135//303 3136//303 3124//303
+f 3124//128 3136//128 3125//128 3113//128
+f 3125//139 3137//139 3138//139 3126//139
+f 3126//138 3138//138 3139//138 3127//138
+f 3127//137 3139//137 3140//137 3128//137
+f 3128//136 3140//136 3141//136 3129//136
+f 3129//304 3141//304 3142//304 3130//304
+f 3130//134 3142//134 3143//134 3131//134
+f 3131//145 3143//145 3144//145 3132//145
+f 3132//144 3144//144 3145//144 3133//144
+f 3133//143 3145//143 3146//143 3134//143
+f 3134//142 3146//142 3147//142 3135//142
+f 3135//305 3147//305 3148//305 3136//305
+f 3136//140 3148//140 3137//140 3125//140
+f 3137//151 3149//151 3150//151 3138//151
+f 3138//150 3150//150 3151//150 3139//150
+f 3139//149 3151//149 3152//149 3140//149
+f 3140//148 3152//148 3153//148 3141//148
+f 3141//306 3153//306 3154//306 3142//306
+f 3142//146 3154//146 3155//146 3143//146
+f 3143//157 3155//157 3156//157 3144//157
+f 3144//156 3156//156 3157//156 3145//156
+f 3145//155 3157//155 3158//155 3146//155
+f 3146//154 3158//154 3159//154 3147//154
+f 3147//153 3159//153 3160//153 3148//153
+f 3148//152 3160//152 3149//152 3137//152
+f 3149//163 3161//163 3162//163 3150//163
+f 3150//162 3162//162 3163//162 3151//162
+f 3151//161 3163//161 3164//161 3152//161
+f 3152//160 3164//160 3165//160 3153//160
+f 3153//159 3165//159 3166//159 3154//159
+f 3154//158 3166//158 3167//158 3155//158
+f 3155//169 3167//169 3168//169 3156//169
+f 3156//168 3168//168 3169//168 3157//168
+f 3157//167 3169//167 3170//167 3158//167
+f 3158//166 3170//166 3171//166 3159//166
+f 3159//165 3171//165 3172//165 3160//165
+f 3160//164 3172//164 3161//164 3149//164
+f 3161//175 3173//175 3174//175 3162//175
+f 3162//174 3174//174 3175//174 3163//174
+f 3163//173 3175//173 3176//173 3164//173
+f 3164//172 3176//172 3177//172 3165//172
+f 3165//171 3177//171 3178//171 3166//171
+f 3166//170 3178//170 3179//170 3167//170
+f 3167//181 3179//181 3180//181 3168//181
+f 3168//180 3180//180 3181//180 3169//180
+f 3169//179 3181//179 3182//179 3170//179
+f 3170//178 3182//178 3183//178 3171//178
+f 3171//177 3183//177 3184//177 3172//177
+f 3172//176 3184//176 3173//176 3161//176
+f 3173//187 3185//187 3186//187 3174//187
+f 3174//186 3186//186 3187//186 3175//186
+f 3175//185 3187//185 3188//185 3176//185
+f 3176//184 3188//184 3189//184 3177//184
+f 3177//183 3189//183 3190//183 3178//183
+f 3178//182 3190//182 3191//182 3179//182
+f 3179//193 3191//193 3192//193 3180//193
+f 3180//192 3192//192 3193//192 3181//192
+f 3181//191 3193//191 3194//191 3182//191
+f 3182//190 3194//190 3195//190 3183//190
+f 3183//189 3195//189 3196//189 3184//189
+f 3184//188 3196//188 3185//188 3173//188
+f 3185//199 3197//199 3198//199 3186//199
+f 3186//198 3198//198 3199//198 3187//198
+f 3187//197 3199//197 3200//197 3188//197
+f 3188//196 3200//196 3201//196 3189//196
+f 3189//195 3201//195 3202//195 3190//195
+f 3190//194 3202//194 3203//194 3191//194
+f 3191//205 3203//205 3204//205 3192//205
+f 3192//307 3204//307 3205//307 3193//307
+f 3193//203 3205//203 3206//203 3194//203
+f 3194//202 3206//202 3207//202 3195//202
+f 3195//308 3207//308 3208//308 3196//308
+f 3196//200 3208//200 3197//200 3185//200
+f 3197//211 3209//211 3210//211 3198//211
+f 3198//210 3210//210 3211//210 3199//210
+f 3199//209 3211//209 3212//209 3200//209
+f 3200//208 3212//208 3213//208 3201//208
+f 3201//207 3213//207 3214//207 3202//207
+f 3202//206 3214//206 3215//206 3203//206
+f 3203//217 3215//217 3216//217 3204//217
+f 3204//309 3216//309 3217//309 3205//309
+f 3205//215 3217//215 3218//215 3206//215
+f 3206//214 3218//214 3219//214 3207//214
+f 3207//310 3219//310 3220//310 3208//310
+f 3208//212 3220//212 3209//212 3197//212
+f 3209//223 3221//223 3222//223 3210//223
+f 3210//222 3222//222 3223//222 3211//222
+f 3211//221 3223//221 3224//221 3212//221
+f 3212//220 3224//220 3225//220 3213//220
+f 3213//219 3225//219 3226//219 3214//219
+f 3214//218 3226//218 3227//218 3215//218
+f 3215//229 3227//229 3228//229 3216//229
+f 3216//311 3228//311 3229//311 3217//311
+f 3217//227 3229//227 3230//227 3218//227
+f 3218//226 3230//226 3231//226 3219//226
+f 3219//225 3231//225 3232//225 3220//225
+f 3220//224 3232//224 3221//224 3209//224
+f 3221//235 3233//235 3234//235 3222//235
+f 3222//234 3234//234 3235//234 3223//234
+f 3223//233 3235//233 3236//233 3224//233
+f 3224//232 3236//232 3237//232 3225//232
+f 3225//231 3237//231 3238//231 3226//231
+f 3226//230 3238//230 3239//230 3227//230
+f 3227//241 3239//241 3240//241 3228//241
+f 3228//312 3240//312 3241//312 3229//312
+f 3229//239 3241//239 3242//239 3230//239
+f 3230//238 3242//238 3243//238 3231//238
+f 3231//237 3243//237 3244//237 3232//237
+f 3232//236 3244//236 3233//236 3221//236
+f 3233//247 3245//247 3246//247 3234//247
+f 3234//246 3246//246 3247//246 3235//246
+f 3235//245 3247//245 3248//245 3236//245
+f 3236//244 3248//244 3249//244 3237//244
+f 3237//243 3249//243 3250//243 3238//243
+f 3238//242 3250//242 3251//242 3239//242
+f 3239//253 3251//253 3252//253 3240//253
+f 3240//252 3252//252 3253//252 3241//252
+f 3241//251 3253//251 3254//251 3242//251
+f 3242//250 3254//250 3255//250 3243//250
+f 3243//249 3255//249 3256//249 3244//249
+f 3244//248 3256//248 3245//248 3233//248
+f 3245//259 3257//259 3258//259 3246//259
+f 3246//258 3258//258 3259//258 3247//258
+f 3247//257 3259//257 3260//257 3248//257
+f 3248//256 3260//256 3261//256 3249//256
+f 3249//255 3261//255 3262//255 3250//255
+f 3250//254 3262//254 3263//254 3251//254
+f 3251//265 3263//265 3264//265 3252//265
+f 3252//264 3264//264 3265//264 3253//264
+f 3253//263 3265//263 3266//263 3254//263
+f 3254//262 3266//262 3267//262 3255//262
+f 3255//313 3267//313 3268//313 3256//313
+f 3256//260 3268//260 3257//260 3245//260
+f 3257//271 3269//271 3270//271 3258//271
+f 3258//270 3270//270 3271//270 3259//270
+f 3259//314 3271//314 3272//314 3260//314
+f 3260//268 3272//268 3273//268 3261//268
+f 3261//267 3273//267 3274//267 3262//267
+f 3262//266 3274//266 3275//266 3263//266
+f 3263//277 3275//277 3276//277 3264//277
+f 3264//276 3276//276 3277//276 3265//276
+f 3265//275 3277//275 3278//275 3266//275
+f 3266//274 3278//274 3279//274 3267//274
+f 3267//315 3279//315 3280//315 3268//315
+f 3268//272 3280//272 3269//272 3257//272
+f 3269//283 2705//283 2708//283 3270//283
+f 3270//282 2708//282 2710//282 3271//282
+f 3271//281 2710//281 2712//281 3272//281
+f 3272//280 2712//280 2714//280 3273//280
+f 3273//279 2714//279 2716//279 3274//279
+f 3274//278 2716//278 2718//278 3275//278
+f 3275//289 2718//289 2720//289 3276//289
+f 3276//316 2720//316 2722//316 3277//316
+f 3277//287 2722//287 2724//287 3278//287
+f 3278//286 2724//286 2726//286 3279//286
+f 3279//317 2726//317 2728//317 3280//317
+f 3280//284 2728//284 2705//284 3269//284
diff --git a/data/torus/torus_with_plane.urdf b/data/torus/torus_with_plane.urdf
new file mode 100644
index 000000000..3db35dec2
--- /dev/null
+++ b/data/torus/torus_with_plane.urdf
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/torus/torus_with_separate_plane.urdf b/data/torus/torus_with_separate_plane.urdf
new file mode 100644
index 000000000..050301f4a
--- /dev/null
+++ b/data/torus/torus_with_separate_plane.urdf
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/tray/tray.jpg b/data/tray/tray.jpg
new file mode 100644
index 000000000..2ce198fb6
Binary files /dev/null and b/data/tray/tray.jpg differ
diff --git a/data/tray/tray_textured2.mtl b/data/tray/tray_textured2.mtl
new file mode 100644
index 000000000..4689a463a
--- /dev/null
+++ b/data/tray/tray_textured2.mtl
@@ -0,0 +1,13 @@
+# Blender MTL File: 'tray_textured2.blend'
+# Material Count: 1
+
+newmtl None
+Ns 0.000000
+Ka 0.000000 0.000000 0.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.800000 0.800000 0.800000
+Ke 0.000000 0.000000 0.000000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd tray.jpg
diff --git a/data/tray/tray_textured2.obj b/data/tray/tray_textured2.obj
new file mode 100644
index 000000000..98a8962c6
--- /dev/null
+++ b/data/tray/tray_textured2.obj
@@ -0,0 +1,255 @@
+# Blender v2.78 (sub 0) OBJ File: 'tray_textured2.blend'
+# www.blender.org
+mtllib tray_textured2.mtl
+o edge_1_Cube.003
+v 0.580000 0.590083 0.250354
+v -0.419960 0.426691 -0.001860
+v -0.580000 0.590083 0.250354
+v 0.580000 0.573309 0.261247
+v 0.420014 0.426691 -0.001059
+v -0.580000 0.573309 0.261247
+v 0.420014 0.409917 0.009834
+v -0.419960 0.409917 0.009033
+vt 0.8346 0.9187
+vt 0.2203 0.8574
+vt 0.1480 0.9187
+vt 0.8346 0.9129
+vt 0.7623 0.8574
+vt 0.1480 0.9129
+vt 0.7623 0.8511
+vt 0.2203 0.8511
+vn 0.0004 0.8386 -0.5448
+vn 0.0001 0.8391 -0.5439
+vn -0.0000 0.8393 -0.5437
+vn 0.8823 -0.2564 -0.3948
+vn -0.0004 -0.8392 0.5439
+vn -0.0001 -0.8386 0.5447
+vn 0.0000 -0.8385 0.5449
+vn -0.8826 -0.2560 -0.3942
+vn 0.0008 -0.5446 -0.8387
+vn -0.0000 0.5446 0.8387
+vn 0.0005 0.8383 -0.5452
+vn -0.0005 -0.8394 0.5435
+usemtl None
+s 1
+f 1/1/1 2/2/2 3/3/3
+f 4/4/4 5/5/4 1/1/4
+f 6/6/5 7/7/6 4/4/7
+f 3/3/8 8/8/8 6/6/8
+f 5/5/9 8/8/9 2/2/9
+f 4/4/10 3/3/10 6/6/10
+f 1/1/1 5/5/11 2/2/2
+f 4/4/4 7/7/4 5/5/4
+f 6/6/5 8/8/12 7/7/6
+f 3/3/8 2/2/8 8/8/8
+f 5/5/9 7/7/9 8/8/9
+f 4/4/10 1/1/10 3/3/10
+o edge_2_Cube
+v 0.590083 0.580000 0.250354
+v 0.409917 0.420060 0.009390
+v 0.573309 0.580000 0.261247
+v 0.590083 -0.580000 0.250354
+v 0.426691 0.420060 -0.001503
+v 0.573309 -0.580000 0.261247
+v 0.426691 -0.419158 -0.002053
+v 0.409917 -0.419158 0.008840
+vt 0.9410 0.8520
+vt 0.7523 0.8566
+vt 0.9234 0.8524
+vt 0.8896 0.1426
+vt 0.7698 0.8562
+vt 0.8721 0.1430
+vt 0.7185 0.1468
+vt 0.7009 0.1472
+vn -0.2561 0.8826 -0.3943
+vn 0.8394 0.0003 -0.5435
+vn 0.8390 0.0001 -0.5441
+vn 0.8389 0.0000 -0.5442
+vn -0.2569 -0.8818 -0.3956
+vn -0.8390 -0.0003 0.5441
+vn -0.8394 -0.0001 0.5436
+vn -0.8395 -0.0000 0.5434
+vn -0.5446 0.0005 -0.8387
+vn 0.5446 -0.0000 0.8387
+vn 0.8396 0.0004 -0.5433
+vn -0.8388 -0.0004 0.5444
+usemtl None
+s 1
+f 9/9/13 10/10/13 11/11/13
+f 12/12/14 13/13/15 9/9/16
+f 14/14/17 15/15/17 12/12/17
+f 11/11/18 16/16/19 14/14/20
+f 13/13/21 16/16/21 10/10/21
+f 12/12/22 11/11/22 14/14/22
+f 9/9/13 13/13/13 10/10/13
+f 12/12/14 15/15/23 13/13/15
+f 14/14/17 16/16/17 15/15/17
+f 11/11/18 10/10/24 16/16/19
+f 13/13/21 15/15/21 16/16/21
+f 12/12/22 9/9/22 11/11/22
+o edge_3_Cube.002
+v 0.580000 -0.573309 0.261247
+v -0.419400 -0.409917 0.008678
+v -0.580000 -0.573309 0.261247
+v 0.580000 -0.590083 0.250354
+v 0.419883 -0.409917 0.009162
+v -0.580000 -0.590083 0.250354
+v 0.419883 -0.426691 -0.001731
+v -0.419400 -0.426691 -0.002215
+vt 0.8690 0.1040
+vt 0.1365 0.1739
+vt 0.0188 0.1040
+vt 0.8690 0.0968
+vt 0.7517 0.1739
+vt 0.0188 0.0968
+vt 0.7517 0.1668
+vt 0.1365 0.1668
+vn -0.0002 0.8392 0.5438
+vn -0.0000 0.8395 0.5433
+vn -0.0000 0.8396 0.5432
+vn 0.8825 0.2562 -0.3945
+vn 0.0002 -0.8396 -0.5433
+vn 0.0000 -0.8392 -0.5438
+vn 0.0000 -0.8391 -0.5439
+vn -0.8821 0.2565 -0.3950
+vn 0.0005 0.5446 -0.8387
+vn 0.0000 -0.5446 0.8387
+vn -0.0003 0.8391 0.5440
+vn 0.0003 -0.8397 -0.5430
+usemtl None
+s 1
+f 17/17/25 18/18/26 19/19/27
+f 20/20/28 21/21/28 17/17/28
+f 22/22/29 23/23/30 20/20/31
+f 19/19/32 24/24/32 22/22/32
+f 21/21/33 24/24/33 18/18/33
+f 20/20/34 19/19/34 22/22/34
+f 17/17/25 21/21/35 18/18/26
+f 20/20/28 23/23/28 21/21/28
+f 22/22/29 24/24/36 23/23/30
+f 19/19/32 18/18/32 24/24/32
+f 21/21/33 23/23/33 24/24/33
+f 20/20/34 17/17/34 19/19/34
+o edge_5_Cube.005
+v -0.153309 0.580000 0.261247
+v -0.006691 0.419400 -0.002214
+v -0.170083 0.580000 0.250354
+v -0.153309 -0.580000 0.261247
+v 0.010083 0.419400 0.008679
+v -0.170083 -0.580000 0.250354
+v 0.010083 -0.419883 0.009732
+v -0.006691 -0.419883 -0.001161
+vt 0.0506 0.8517
+vt 0.1935 0.8492
+vt 0.0342 0.8520
+vt 0.0164 0.1914
+vt 0.2099 0.8489
+vt 0.0001 0.1917
+vt 0.1757 0.1886
+vt 0.1594 0.1889
+vn 0.2565 0.8821 -0.3950
+vn 0.8387 0.0005 0.5446
+vn 0.8394 0.0001 0.5434
+vn 0.8396 0.0000 0.5432
+vn 0.2565 -0.8822 -0.3950
+vn -0.8395 -0.0005 -0.5434
+vn -0.8388 -0.0001 -0.5445
+vn -0.8386 -0.0000 -0.5448
+vn 0.5446 -0.0011 -0.8387
+vn -0.5446 -0.0000 0.8387
+vn 0.8384 0.0007 0.5451
+vn -0.8398 -0.0007 -0.5429
+usemtl None
+s 1
+f 25/25/37 26/26/37 27/27/37
+f 28/28/38 29/29/39 25/25/40
+f 30/30/41 31/31/41 28/28/41
+f 27/27/42 32/32/43 30/30/44
+f 29/29/45 32/32/45 26/26/45
+f 28/28/46 27/27/46 30/30/46
+f 25/25/37 29/29/37 26/26/37
+f 28/28/38 31/31/47 29/29/39
+f 30/30/41 32/32/41 31/31/41
+f 27/27/42 26/26/48 32/32/43
+f 29/29/45 31/31/45 32/32/45
+f 28/28/46 25/25/46 27/27/46
+o edge_4_Cube.001
+v -0.573309 0.580000 0.261247
+v -0.426691 0.419400 -0.002214
+v -0.590083 0.580000 0.250354
+v -0.573309 -0.580000 0.261247
+v -0.409917 0.419400 0.008679
+v -0.590083 -0.580000 0.250354
+v -0.409917 -0.419400 0.009162
+v -0.426691 -0.419400 -0.001731
+vt 0.9046 0.2397
+vt 0.7929 0.2434
+vt 0.9174 0.2393
+vt 0.9537 0.7559
+vt 0.7801 0.2438
+vt 0.9664 0.7554
+vt 0.8291 0.7599
+vt 0.8419 0.7595
+vn 0.2565 0.8821 -0.3950
+vn 0.8392 0.0002 0.5438
+vn 0.8395 0.0000 0.5433
+vn 0.8396 0.0000 0.5432
+vn 0.2568 -0.8819 -0.3954
+vn -0.8396 -0.0002 -0.5433
+vn -0.8392 -0.0000 -0.5438
+vn -0.8391 -0.0000 -0.5439
+vn 0.5446 -0.0005 -0.8387
+vn -0.5446 -0.0000 0.8387
+vn 0.8391 0.0003 0.5440
+vn -0.8397 -0.0003 -0.5430
+usemtl None
+s 1
+f 33/33/49 34/34/49 35/35/49
+f 36/36/50 37/37/51 33/33/52
+f 38/38/53 39/39/53 36/36/53
+f 35/35/54 40/40/55 38/38/56
+f 37/37/57 40/40/57 34/34/57
+f 36/36/58 35/35/58 38/38/58
+f 33/33/49 37/37/49 34/34/49
+f 36/36/50 39/39/59 37/37/51
+f 38/38/53 40/40/53 39/39/53
+f 35/35/54 34/34/60 40/40/55
+f 37/37/57 39/39/57 40/40/57
+f 36/36/58 33/33/58 35/35/58
+o base_Cube.004
+v 0.420000 0.420000 0.010000
+v -0.420000 0.420000 -0.010000
+v -0.420000 0.420000 0.010000
+v 0.420000 -0.420000 0.010000
+v 0.420000 0.420000 -0.010000
+v -0.420000 -0.420000 0.010000
+v 0.420000 -0.420000 -0.010000
+v -0.420000 -0.420000 -0.010000
+vt 0.7524 0.8072
+vt -0.3038 0.8371
+vt -0.3038 0.8371
+vt 0.7012 0.1905
+vt 0.7524 0.8072
+vt -0.3550 0.2204
+vt 0.7012 0.1905
+vt -0.3550 0.2204
+vn -0.0000 1.0000 0.0000
+vn 1.0000 0.0000 0.0000
+vn 0.0000 -1.0000 0.0000
+vn -1.0000 -0.0000 0.0000
+vn -0.0000 0.0000 -1.0000
+vn 0.0000 -0.0000 1.0000
+usemtl None
+s 1
+f 41/41/61 42/42/61 43/43/61
+f 44/44/62 45/45/62 41/41/62
+f 46/46/63 47/47/63 44/44/63
+f 43/43/64 48/48/64 46/46/64
+f 45/45/65 48/48/65 42/42/65
+f 44/44/66 43/43/66 46/46/66
+f 41/41/61 45/45/61 42/42/61
+f 44/44/62 47/47/62 45/45/62
+f 46/46/63 48/48/63 47/47/63
+f 43/43/64 42/42/64 48/48/64
+f 45/45/65 47/47/65 48/48/65
+f 44/44/66 41/41/66 43/43/66
diff --git a/data/tray/tray_textured2.urdf b/data/tray/tray_textured2.urdf
new file mode 100644
index 000000000..8b89b015c
--- /dev/null
+++ b/data/tray/tray_textured2.urdf
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/pybullet_quickstartguide.pdf b/docs/pybullet_quickstartguide.pdf
new file mode 100644
index 000000000..d1e10cca7
Binary files /dev/null and b/docs/pybullet_quickstartguide.pdf differ
diff --git a/examples/BasicDemo/premake4.lua b/examples/BasicDemo/premake4.lua
index dd924249e..2faa974cd 100644
--- a/examples/BasicDemo/premake4.lua
+++ b/examples/BasicDemo/premake4.lua
@@ -18,6 +18,7 @@ language "C++"
files {
"**.cpp",
"**.h",
+ "../CommonInterfaces/*",
}
@@ -49,6 +50,7 @@ files {
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
+ "../CommonInterfaces/*",
"../Utils/b3Clock.cpp",
"../Utils/b3Clock.h",
}
@@ -90,6 +92,7 @@ files {
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
+ "../CommonInterfaces/*",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
"../TinyRenderer/tgaimage.cpp",
@@ -130,6 +133,7 @@ files {
"*.h",
"../StandaloneMain/main_tinyrenderer_single_example.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
+ "../CommonInterfaces/*",
"../OpenGLWindow/SimpleCamera.cpp",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
@@ -175,6 +179,7 @@ files {
"BasicExample.cpp",
"*.h",
"../StandaloneMain/hellovr_opengl_main.cpp",
+ "../CommonInterfaces/*",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
@@ -200,4 +205,4 @@ if os.is("MacOSX") then
links{"Cocoa.framework"}
end
-end
\ No newline at end of file
+end
diff --git a/examples/Benchmarks/BenchmarkDemo.cpp b/examples/Benchmarks/BenchmarkDemo.cpp
index f659d017c..00ac36b9c 100644
--- a/examples/Benchmarks/BenchmarkDemo.cpp
+++ b/examples/Benchmarks/BenchmarkDemo.cpp
@@ -32,10 +32,12 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btTransform.h"
+#include "../MultiThreadedDemo/ParallelFor.h"
class btDynamicsWorld;
#define NUMRAYS 500
+#define USE_PARALLEL_RAYCASTS 1
class btRigidBody;
class btBroadphaseInterface;
@@ -47,11 +49,11 @@ struct btCollisionAlgorithmCreateFunc;
class btDefaultCollisionConfiguration;
-#include "../CommonInterfaces/CommonRigidBodyBase.h"
+#include "../MultiThreadedDemo/CommonRigidBodyMTBase.h"
-class BenchmarkDemo : public CommonRigidBodyBase
+class BenchmarkDemo : public CommonRigidBodyMTBase
{
//keep the collision shapes, for deletion/cleanup
@@ -91,7 +93,7 @@ class BenchmarkDemo : public CommonRigidBodyBase
public:
BenchmarkDemo(struct GUIHelperInterface* helper, int benchmark)
- :CommonRigidBodyBase(helper),
+ :CommonRigidBodyMTBase(helper),
m_benchmark(benchmark)
{
}
@@ -204,7 +206,39 @@ public:
sign = -1.0;
}
- void cast (btCollisionWorld* cw)
+ void castRays( btCollisionWorld* cw, int iBegin, int iEnd )
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
+
+ cw->rayTest (source[i], dest[i], cb);
+ if (cb.hasHit ())
+ {
+ hit[i] = cb.m_hitPointWorld;
+ normal[i] = cb.m_hitNormalWorld;
+ normal[i].normalize ();
+ } else {
+ hit[i] = dest[i];
+ normal[i] = btVector3(1.0, 0.0, 0.0);
+ }
+
+ }
+ }
+
+ struct CastRaysLoopBody
+ {
+ btRaycastBar2* mRaycasts;
+ btCollisionWorld* mWorld;
+ CastRaysLoopBody(btCollisionWorld* cw, btRaycastBar2* rb) : mWorld(cw), mRaycasts(rb) {}
+
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ mRaycasts->castRays(mWorld, iBegin, iEnd);
+ }
+ };
+
+ void cast (btCollisionWorld* cw, bool multiThreading = false)
{
#ifdef USE_BT_CLOCK
frame_timer.reset ();
@@ -228,22 +262,19 @@ public:
normal[i].normalize ();
}
#else
- for (int i = 0; i < NUMRAYS; i++)
- {
- btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
-
- cw->rayTest (source[i], dest[i], cb);
- if (cb.hasHit ())
- {
- hit[i] = cb.m_hitPointWorld;
- normal[i] = cb.m_hitNormalWorld;
- normal[i].normalize ();
- } else {
- hit[i] = dest[i];
- normal[i] = btVector3(1.0, 0.0, 0.0);
- }
-
- }
+#if USE_PARALLEL_RAYCASTS
+ if ( multiThreading )
+ {
+ CastRaysLoopBody rayLooper(cw, this);
+ int grainSize = 20; // number of raycasts per task
+ parallelFor( 0, NUMRAYS, grainSize, rayLooper );
+ }
+ else
+#endif // USE_PARALLEL_RAYCASTS
+ {
+ // single threaded
+ castRays(cw, 0, NUMRAYS);
+ }
#ifdef USE_BT_CLOCK
ms += frame_timer.getTimeMilliseconds ();
#endif //USE_BT_CLOCK
@@ -354,42 +385,43 @@ void BenchmarkDemo::initPhysics()
setCameraDistance(btScalar(100.));
- ///collision configuration contains default setup for memory, collision setup
- btDefaultCollisionConstructionInfo cci;
- cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
- m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
+ createEmptyDynamicsWorld();
+ /////collision configuration contains default setup for memory, collision setup
+ //btDefaultCollisionConstructionInfo cci;
+ //cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
+ //m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
- ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
- m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
-
- m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
+ /////use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
+ //m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
+ //
+ //m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
- ///the maximum size of the collision world. Make sure objects stay within these boundaries
- ///Don't make the world AABB size too large, it will harm simulation quality and performance
- btVector3 worldAabbMin(-1000,-1000,-1000);
- btVector3 worldAabbMax(1000,1000,1000);
-
- btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
- m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
+ /////the maximum size of the collision world. Make sure objects stay within these boundaries
+ /////Don't make the world AABB size too large, it will harm simulation quality and performance
+ //btVector3 worldAabbMin(-1000,-1000,-1000);
+ //btVector3 worldAabbMax(1000,1000,1000);
+ //
+ //btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
+ //m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
// m_broadphase = new btSimpleBroadphase();
// m_broadphase = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
- btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
+ //btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
- m_solver = sol;
+ //m_solver = sol;
- btDiscreteDynamicsWorld* dynamicsWorld;
- m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+ //btDiscreteDynamicsWorld* dynamicsWorld;
+ //m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
///the following 3 lines increase the performance dramatically, with a little bit of loss of quality
m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; //don't recalculate friction values each frame
- dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations
+ m_dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations
//m_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...);
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
@@ -1242,7 +1274,7 @@ void BenchmarkDemo::initRays()
void BenchmarkDemo::castRays()
{
- raycastBar.cast (m_dynamicsWorld);
+ raycastBar.cast (m_dynamicsWorld, m_multithreadedWorld);
}
void BenchmarkDemo::createTest7()
@@ -1264,7 +1296,7 @@ void BenchmarkDemo::exitPhysics()
}
m_ragdolls.clear();
- CommonRigidBodyBase::exitPhysics();
+ CommonRigidBodyMTBase::exitPhysics();
}
diff --git a/examples/CommonInterfaces/CommonGUIHelperInterface.h b/examples/CommonInterfaces/CommonGUIHelperInterface.h
index baea8daf4..01f7b3728 100644
--- a/examples/CommonInterfaces/CommonGUIHelperInterface.h
+++ b/examples/CommonInterfaces/CommonGUIHelperInterface.h
@@ -69,6 +69,12 @@ struct GUIHelperInterface
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)=0;
+
+ virtual int addUserDebugText3D( const char* txt, const double posisionXYZ[3], const double textColorRGB[3], double size, double lifeTime)=0;
+ virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime )=0;
+ virtual void removeUserDebugItem( int debugItemUniqueId)=0;
+ virtual void removeAllUserDebugItems( )=0;
+
};
@@ -141,7 +147,22 @@ struct DummyGUIHelper : public GUIHelperInterface
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)
{
}
-
+
+ virtual int addUserDebugText3D( const char* txt, const double positionXYZ[3], const double textColorRGB[3], double size, double lifeTime)
+ {
+ return -1;
+ }
+ virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime )
+ {
+ return -1;
+ }
+ virtual void removeUserDebugItem( int debugItemUniqueId)
+ {
+ }
+ virtual void removeAllUserDebugItems( )
+ {
+ }
+
};
#endif //GUI_HELPER_INTERFACE_H
diff --git a/examples/CommonInterfaces/CommonGraphicsAppInterface.h b/examples/CommonInterfaces/CommonGraphicsAppInterface.h
index 674807de8..31f0f51ce 100644
--- a/examples/CommonInterfaces/CommonGraphicsAppInterface.h
+++ b/examples/CommonInterfaces/CommonGraphicsAppInterface.h
@@ -120,7 +120,7 @@ struct CommonGraphicsApp
virtual int getUpAxis() const = 0;
virtual void swapBuffer() = 0;
- virtual void drawText( const char* txt, int posX, int posY) = 0;
+ virtual void drawText( const char* txt, int posX, int posY, float size = 1.0f) = 0;
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)=0;
virtual void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA)=0;
virtual int registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ, int textureIndex = -1, float textureScaling = 1)=0;
diff --git a/examples/CommonInterfaces/CommonParameterInterface.h b/examples/CommonInterfaces/CommonParameterInterface.h
index 3bb2f50c8..e2334108c 100644
--- a/examples/CommonInterfaces/CommonParameterInterface.h
+++ b/examples/CommonInterfaces/CommonParameterInterface.h
@@ -4,7 +4,7 @@
#pragma once
-typedef void (*SliderParamChangedCallback) (float newVal);
+typedef void (*SliderParamChangedCallback) (float newVal, void* userPointer);
#include "LinearMath/btScalar.h"
struct SliderParams
@@ -16,6 +16,7 @@ struct SliderParams
btScalar* m_paramValuePointer;
void* m_userPointer;
bool m_clampToNotches;
+ bool m_clampToIntegers;
bool m_showValues;
SliderParams(const char* name, btScalar* targetValuePointer)
@@ -26,6 +27,7 @@ struct SliderParams
m_paramValuePointer(targetValuePointer),
m_userPointer(0),
m_clampToNotches(true),
+ m_clampToIntegers(false),
m_showValues(true)
{
}
diff --git a/examples/Evolution/NN3DWalkers.cpp b/examples/Evolution/NN3DWalkers.cpp
index 3a4eb32fc..67718c970 100755
--- a/examples/Evolution/NN3DWalkers.cpp
+++ b/examples/Evolution/NN3DWalkers.cpp
@@ -950,9 +950,9 @@ bool NN3DWalkersExample::keyboardCallback(int key, int state)
case ']':
gWalkerMotorStrength *= 1.1f;
return true;
-// case 'l':
+ case 'l':
// printWalkerConfigs();
-// return true;
+ return true;
default:
break;
}
diff --git a/examples/Evolution/NN3DWalkersTimeWarpBase.h b/examples/Evolution/NN3DWalkersTimeWarpBase.h
index 98385d00a..31142ed07 100644
--- a/examples/Evolution/NN3DWalkersTimeWarpBase.h
+++ b/examples/Evolution/NN3DWalkersTimeWarpBase.h
@@ -138,19 +138,15 @@ static btScalar gCFMSingularityAvoidance = 0;
//GUI related parameter changing helpers
-inline void floorSliderValues(float notUsed) { // floor values that should be ints
- gSolverIterations = floor(gSolverIterations);
-}
-
-inline void twxChangePhysicsStepsPerSecond(float physicsStepsPerSecond) { // function to change simulation physics steps per second
+inline void twxChangePhysicsStepsPerSecond(float physicsStepsPerSecond, void*) { // function to change simulation physics steps per second
gPhysicsStepsPerSecond = physicsStepsPerSecond;
}
-inline void twxChangeFPS(float framesPerSecond) {
+inline void twxChangeFPS(float framesPerSecond, void*) {
gFramesPerSecond = framesPerSecond;
}
-inline void twxChangeERPCFM(float notUsed) { // function to change ERP/CFM appropriately
+inline void twxChangeERPCFM(float notUsed, void*) { // function to change ERP/CFM appropriately
gChangeErpCfm = true;
}
@@ -166,13 +162,12 @@ inline void changeSolver(int comboboxId, const char* item, void* userPointer) {
}
-inline void twxChangeSolverIterations(float notUsed){ // change the solver iterations
+inline void twxChangeSolverIterations(float notUsed, void* userPtr) { // change the solver iterations
- floorSliderValues(0); // floor the values set by slider
}
-inline void clampToCustomSpeedNotches(float speed) { // function to clamp to custom speed notches
+inline void clampToCustomSpeedNotches(float speed, void*) { // function to clamp to custom speed notches
double minSpeed = 0;
double minSpeedDist = SimulationSpeeds::MAX_SPEED;
for (int i = 0; i < SimulationSpeeds::NUM_SPEEDS; i++) {
@@ -200,7 +195,7 @@ inline void switchMaximumSpeed(int buttonId, bool buttonState, void* userPointer
// b3Printf("Run maximum speed %s", gMaximumSpeed?"on":"off");
}
-inline void setApplicationTick(float frequency){ // set internal application tick
+inline void setApplicationTick(float frequency, void*){ // set internal application tick
gApplicationTick = 1000.0f/frequency;
}
@@ -384,7 +379,7 @@ struct NN3DWalkersTimeWarpBase: public CommonRigidBodyBase {
slider.m_minVal = 0;
slider.m_maxVal = 1000;
slider.m_callback = twxChangePhysicsStepsPerSecond;
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt
index 024d928d3..0096560b6 100644
--- a/examples/ExampleBrowser/CMakeLists.txt
+++ b/examples/ExampleBrowser/CMakeLists.txt
@@ -108,6 +108,29 @@ ELSE(WIN32)
ENDIF(APPLE)
ENDIF(WIN32)
+IF (BULLET2_MULTITHREADED_OPEN_MP_DEMO)
+ ADD_DEFINITIONS("-DBT_USE_OPENMP=1")
+ IF (MSVC)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp")
+ ELSE (MSVC)
+ # GCC, Clang
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
+ ENDIF (MSVC)
+ENDIF (BULLET2_MULTITHREADED_OPEN_MP_DEMO)
+
+IF (BULLET2_MULTITHREADED_PPL_DEMO)
+ ADD_DEFINITIONS("-DBT_USE_PPL=1")
+ENDIF (BULLET2_MULTITHREADED_PPL_DEMO)
+
+IF (BULLET2_MULTITHREADED_TBB_DEMO)
+ SET (BULLET2_TBB_INCLUDE_DIR "not found" CACHE PATH "Directory for Intel TBB includes.")
+ SET (BULLET2_TBB_LIB_DIR "not found" CACHE PATH "Directory for Intel TBB libraries.")
+ find_library(TBB_LIBRARY tbb PATHS ${BULLET2_TBB_LIB_DIR})
+ find_library(TBBMALLOC_LIBRARY tbbmalloc PATHS ${BULLET2_TBB_LIB_DIR})
+ ADD_DEFINITIONS("-DBT_USE_TBB=1")
+ INCLUDE_DIRECTORIES( ${BULLET2_TBB_INCLUDE_DIR} )
+ LINK_LIBRARIES( ${TBB_LIBRARY} ${TBBMALLOC_LIBRARY} )
+ENDIF (BULLET2_MULTITHREADED_TBB_DEMO)
SET(ExtendedTutorialsSources
../ExtendedTutorials/Chain.cpp
@@ -146,6 +169,7 @@ SET(BulletExampleBrowser_SRCS
../SharedMemory/PhysicsServer.cpp
../SharedMemory/PhysicsClientSharedMemory.cpp
+ ../SharedMemory/PhysicsClientSharedMemory_C_API.cpp
../SharedMemory/PhysicsClient.cpp
../SharedMemory/PhysicsClientC_API.cpp
../SharedMemory/PhysicsServerExample.cpp
@@ -173,6 +197,11 @@ SET(BulletExampleBrowser_SRCS
../InverseKinematics/InverseKinematicsExample.h
../ForkLift/ForkLiftDemo.cpp
../ForkLift/ForkLiftDemo.h
+ ../MultiThreadedDemo/MultiThreadedDemo.cpp
+ ../MultiThreadedDemo/MultiThreadedDemo.h
+ ../MultiThreadedDemo/CommonRigidBodyMTBase.cpp
+ ../MultiThreadedDemo/CommonRigidBodyMTBase.h
+ ../MultiThreadedDemo/ParallelFor.h
../Tutorial/Tutorial.cpp
../Tutorial/Tutorial.h
../Tutorial/Dof6ConstraintTutorial.cpp
@@ -346,9 +375,26 @@ ADD_CUSTOM_COMMAND(
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory ${BULLET_PHYSICS_SOURCE_DIR}/data ${PROJECT_BINARY_DIR}/data
)
+IF (BULLET2_MULTITHREADED_TBB_DEMO AND WIN32)
+ # add a post build command to copy some dlls to the executable directory
+ set(TBB_VC_VER "vc12")
+ set(TBB_VC_ARCH "ia32")
+ # assume 32-bit build in VC12 for now
+ # checks can be added here at a later time
+ ADD_CUSTOM_COMMAND(TARGET App_ExampleBrowser POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${BULLET2_TBB_INCLUDE_DIR}/../bin/${TBB_VC_ARCH}/${TBB_VC_VER}/tbb.dll"
+ $)
+ ADD_CUSTOM_COMMAND(TARGET App_ExampleBrowser POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${BULLET2_TBB_INCLUDE_DIR}/../bin/${TBB_VC_ARCH}/${TBB_VC_VER}/tbbmalloc.dll"
+ $)
+ENDIF (BULLET2_MULTITHREADED_TBB_DEMO AND WIN32)
+
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(App_ExampleBrowser PROPERTIES DEBUG_POSTFIX "_Debug")
SET_TARGET_PROPERTIES(App_ExampleBrowser PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
SET_TARGET_PROPERTIES(App_ExampleBrowser PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
+
diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp
index 87382fbc8..f6af39031 100644
--- a/examples/ExampleBrowser/ExampleEntries.cpp
+++ b/examples/ExampleBrowser/ExampleEntries.cpp
@@ -8,6 +8,7 @@
#include "../RenderingExamples/TinyRendererSetup.h"
#include "../RenderingExamples/DynamicTexturedCubeDemo.h"
#include "../ForkLift/ForkLiftDemo.h"
+#include "../MultiThreadedDemo/MultiThreadedDemo.h"
#include "../BasicDemo/BasicExample.h"
#include "../Planar2D/Planar2D.h"
#include "../Benchmarks/BenchmarkDemo.h"
@@ -269,6 +270,7 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(1,"Two Point Grasp","Grasp experiment with two point contact to test rolling friction", GripperGraspExampleCreateFunc, eTWO_POINT_GRASP),
ExampleEntry(1,"One Motor Gripper Grasp","Grasp experiment with a gripper with one motor to test slider constraint for closed loop structure", GripperGraspExampleCreateFunc, eONE_MOTOR_GRASP),
ExampleEntry(1,"Grasp Soft Body","Grasp soft body experiment", GripperGraspExampleCreateFunc, eGRASP_SOFT_BODY),
+ ExampleEntry(1,"Softbody Multibody Coupling","Two way coupling between soft body and multibody experiment", GripperGraspExampleCreateFunc, eSOFTBODY_MULTIBODY_COUPLING),
#ifdef ENABLE_LUA
@@ -284,7 +286,13 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(1,"Fracture demo", "Create a basic custom implementation to model fracturing objects, based on a btCompoundShape. It explicitly propagates the collision impulses and breaks the rigid body into multiple rigid bodies. Press F to toggle fracture and glue mode.", FractureDemoCreateFunc),
ExampleEntry(1,"Planar 2D","Show the use of 2D collision shapes and rigid body simulation. The collision shape is wrapped into a btConvex2dShape. The rigid bodies are restricted in a plane using the 'setAngularFactor' and 'setLinearFactor' API call.",Planar2DCreateFunc),
-
+#if BT_USE_OPENMP || BT_USE_TBB || BT_USE_PPL
+ // only enable MultiThreaded demo if a task scheduler is available
+ ExampleEntry( 1, "Multithreaded Demo",
+ "Stacks of boxes that do not sleep. Good for testing performance with large numbers of bodies and contacts. Sliders can be used to change the number of stacks (restart needed after each change)."
+ ,
+ MultiThreadedDemoCreateFunc ),
+#endif
ExampleEntry(0,"Rendering"),
diff --git a/examples/ExampleBrowser/GL_ShapeDrawer.cpp b/examples/ExampleBrowser/GL_ShapeDrawer.cpp
index 99b6421d6..2b730af5b 100644
--- a/examples/ExampleBrowser/GL_ShapeDrawer.cpp
+++ b/examples/ExampleBrowser/GL_ShapeDrawer.cpp
@@ -782,7 +782,7 @@ GL_ShapeDrawer::~GL_ShapeDrawer()
}
}
-void GL_ShapeDrawer::drawSceneInternal(const btDiscreteDynamicsWorld* dynamicsWorld, int pass)
+void GL_ShapeDrawer::drawSceneInternal(const btDiscreteDynamicsWorld* dynamicsWorld, int pass, int cameraUpAxis)
{
btAssert(dynamicsWorld);
@@ -849,7 +849,12 @@ void GL_ShapeDrawer::drawSceneInternal(const btDiscreteDynamicsWorld* dynamicsWo
//if (!(getDebugMode()& btIDebugDraw::DBG_DrawWireframe))
int debugMode = 0;//getDebugMode()
//btVector3 m_sundirection(-1,-1,-1);
+
btVector3 m_sundirection(btVector3(1,-2,1)*1000);
+ if (cameraUpAxis==2)
+ {
+ m_sundirection = btVector3(1,1,-2)*1000;
+ }
switch(pass)
{
@@ -861,9 +866,12 @@ void GL_ShapeDrawer::drawSceneInternal(const btDiscreteDynamicsWorld* dynamicsWo
}
-void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, bool useShadows)
+//this GL_ShapeDrawer will be removed, in the meanwhile directly access this global 'useShadoMaps'
+extern bool useShadowMap;
+void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, bool useShadows1, int cameraUpAxis)
{
+ bool useShadows = useShadowMap;
GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) };
GLfloat light_diffuse[] = { btScalar(1.0), btScalar(1.0), btScalar(1.0), btScalar(1.0) };
GLfloat light_specular[] = { btScalar(1.0), btScalar(1.0), btScalar(1.0), btScalar(1.0 )};
@@ -897,7 +905,7 @@ void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, boo
{
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_CULL_FACE);
- drawSceneInternal(dynamicsWorld,0);
+ drawSceneInternal(dynamicsWorld,0, cameraUpAxis);
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
@@ -907,10 +915,10 @@ void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, boo
glStencilFunc(GL_ALWAYS,1,0xFFFFFFFFL);
glFrontFace(GL_CCW);
glStencilOp(GL_KEEP,GL_KEEP,GL_INCR);
- drawSceneInternal(dynamicsWorld,1);
+ drawSceneInternal(dynamicsWorld,1,cameraUpAxis);
glFrontFace(GL_CW);
glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
- drawSceneInternal(dynamicsWorld,1);
+ drawSceneInternal(dynamicsWorld,1,cameraUpAxis);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT,GL_FILL);
@@ -929,7 +937,7 @@ void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, boo
glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glDisable(GL_LIGHTING);
- drawSceneInternal(dynamicsWorld,2);
+ drawSceneInternal(dynamicsWorld,2,cameraUpAxis);
glEnable(GL_LIGHTING);
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
@@ -938,6 +946,6 @@ void GL_ShapeDrawer::drawScene(const btDiscreteDynamicsWorld* dynamicsWorld, boo
else
{
glDisable(GL_CULL_FACE);
- drawSceneInternal(dynamicsWorld,0);
+ drawSceneInternal(dynamicsWorld,0,cameraUpAxis);
}
}
\ No newline at end of file
diff --git a/examples/ExampleBrowser/GL_ShapeDrawer.h b/examples/ExampleBrowser/GL_ShapeDrawer.h
index 4d9ce701a..e004420c4 100644
--- a/examples/ExampleBrowser/GL_ShapeDrawer.h
+++ b/examples/ExampleBrowser/GL_ShapeDrawer.h
@@ -44,7 +44,7 @@ protected:
ShapeCache* cache(btConvexShape*);
- virtual void drawSceneInternal(const btDiscreteDynamicsWorld* world, int pass);
+ virtual void drawSceneInternal(const btDiscreteDynamicsWorld* world, int pass, int cameraUpAxis);
public:
GL_ShapeDrawer();
@@ -53,7 +53,7 @@ public:
- virtual void drawScene(const btDiscreteDynamicsWorld* world, bool useShadows);
+ virtual void drawScene(const btDiscreteDynamicsWorld* world, bool useShadows, int cameraUpAxis);
///drawOpenGL might allocate temporary memoty, stores pointer in shape userpointer
virtual void drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax);
diff --git a/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp b/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp
index 449f27e0a..aa8c0b871 100644
--- a/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp
+++ b/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp
@@ -28,18 +28,20 @@ template
struct MySliderEventHandler : public Gwen::Event::Handler
{
SliderParamChangedCallback m_callback;
+ void* m_userPointer;
Gwen::Controls::TextBox* m_label;
Gwen::Controls::Slider* m_pSlider;
char m_variableName[1024];
T* m_targetValue;
bool m_showValue;
- MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target,SliderParamChangedCallback callback)
+ MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target, SliderParamChangedCallback callback, void* userPtr)
:m_label(label),
m_pSlider(pSlider),
m_targetValue(target),
m_showValue(true),
- m_callback(callback)
+ m_callback(callback),
+ m_userPointer(userPtr)
{
memcpy(m_variableName,varName,strlen(varName)+1);
}
@@ -55,7 +57,7 @@ struct MySliderEventHandler : public Gwen::Event::Handler
if (m_callback)
{
- (*m_callback)(v);
+ (*m_callback)(v, m_userPointer);
}
}
@@ -223,12 +225,20 @@ void GwenParameterInterface::registerSliderFloatParameter(SliderParams& params)
pSlider->SetPos( 10, m_gwenInternalData->m_curYposition );
pSlider->SetSize( 200, 20 );
pSlider->SetRange( params.m_minVal, params.m_maxVal);
- pSlider->SetNotchCount(16);//float(params.m_maxVal-params.m_minVal)/100.f);
- pSlider->SetClampToNotches( params.m_clampToNotches );
+ if (params.m_clampToIntegers)
+ {
+ pSlider->SetNotchCount( int( params.m_maxVal - params.m_minVal ) );
+ pSlider->SetClampToNotches( params.m_clampToNotches );
+ }
+ else
+ {
+ pSlider->SetNotchCount( 16 );//float(params.m_maxVal-params.m_minVal)/100.f);
+ pSlider->SetClampToNotches( params.m_clampToNotches );
+ }
pSlider->SetValue( *params.m_paramValuePointer);//dimensions[i] );
char labelName[1024];
sprintf(labelName,"%s",params.m_name);//axisNames[0]);
- MySliderEventHandler* handler = new MySliderEventHandler(labelName,label,pSlider,params.m_paramValuePointer,params.m_callback);
+ MySliderEventHandler* handler = new MySliderEventHandler(labelName,label,pSlider,params.m_paramValuePointer,params.m_callback, params.m_userPointer);
handler->m_showValue = params.m_showValues;
m_paramInternalData->m_sliderEventHandlers.push_back(handler);
diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp
index 70e717159..ca86cda97 100644
--- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp
+++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp
@@ -134,9 +134,9 @@ int gSharedMemoryKey=-1;
int gPreferredOpenCLDeviceIndex=-1;
int gPreferredOpenCLPlatformIndex=-1;
-int gGpuArraySizeX=15;
-int gGpuArraySizeY=15;
-int gGpuArraySizeZ=15;
+int gGpuArraySizeX=45;
+int gGpuArraySizeY=55;
+int gGpuArraySizeZ=45;
//#include
//unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM);
@@ -1167,7 +1167,7 @@ void OpenGLExampleBrowser::update(float deltaTime)
}
BT_PROFILE("Render Scene");
sCurrentDemo->renderScene();
- }
+ } else
{
B3_PROFILE("physicsDebugDraw");
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp
index 4a4277b2d..0194b4f4e 100644
--- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp
+++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp
@@ -338,7 +338,7 @@ void OpenGLGuiHelper::render(const btDiscreteDynamicsWorld* rbWorld)
if (m_data->m_gl2ShapeDrawer && rbWorld)
{
m_data->m_gl2ShapeDrawer->enableTexture(true);
- m_data->m_gl2ShapeDrawer->drawScene(rbWorld,true);
+ m_data->m_gl2ShapeDrawer->drawScene(rbWorld,true, m_data->m_glApp->getUpAxis());
}
}
void OpenGLGuiHelper::createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld)
diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.h b/examples/ExampleBrowser/OpenGLGuiHelper.h
index eaa72a7be..d0c9cdb2b 100644
--- a/examples/ExampleBrowser/OpenGLGuiHelper.h
+++ b/examples/ExampleBrowser/OpenGLGuiHelper.h
@@ -55,9 +55,27 @@ struct OpenGLGuiHelper : public GUIHelperInterface
virtual void drawText3D( const char* txt, float posX, float posY, float posZ, float size);
+ virtual int addUserDebugText3D( const char* txt, const double positionXYZ[3], const double textColorRGB[3], double size, double lifeTime)
+ {
+ return -1;
+ }
+ virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime )
+ {
+ return -1;
+ }
+ virtual void removeUserDebugItem( int debugItemUniqueId)
+ {
+ }
+ virtual void removeAllUserDebugItems( )
+ {
+ }
+
+
void renderInternalGl2(int pass, const btDiscreteDynamicsWorld* dynamicsWorld);
void setVRMode(bool vrMode);
+
+
};
#endif //OPENGL_GUI_HELPER_H
diff --git a/examples/ExampleBrowser/main.cpp b/examples/ExampleBrowser/main.cpp
index d0f132c1a..05985d41e 100644
--- a/examples/ExampleBrowser/main.cpp
+++ b/examples/ExampleBrowser/main.cpp
@@ -15,6 +15,8 @@
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
#include "../Importers/ImportSDFDemo/ImportSDFSetup.h"
#include "../Importers/ImportSTLDemo/ImportSTLSetup.h"
+#include "../Importers/ImportBullet/SerializeSetup.h"
+
#include "LinearMath/btAlignedAllocator.h"
@@ -34,6 +36,8 @@ int main(int argc, char* argv[])
exampleBrowser->registerFileImporter(".sdf", ImportSDFCreateFunc);
exampleBrowser->registerFileImporter(".obj", ImportObjCreateFunc);
exampleBrowser->registerFileImporter(".stl", ImportSTLCreateFunc);
+ exampleBrowser->registerFileImporter(".bullet", SerializeBulletCreateFunc);
+
clock.reset();
if (init)
diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua
index c28ae0e5a..ac184dedc 100644
--- a/examples/ExampleBrowser/premake4.lua
+++ b/examples/ExampleBrowser/premake4.lua
@@ -63,6 +63,14 @@ project "App_BulletExampleBrowser"
"../SharedMemory/PhysicsServer.cpp",
"../SharedMemory/PhysicsServerSharedMemory.cpp",
"../SharedMemory/PhysicsClientSharedMemory.cpp",
+ "../SharedMemory/PhysicsClientSharedMemory_C_API.cpp",
+ "../SharedMemory/PhysicsClientSharedMemory_C_API.h",
+ "../SharedMemory/PhysicsClientSharedMemory2.cpp",
+ "../SharedMemory/PhysicsClientSharedMemory2.h",
+ "../SharedMemory/PhysicsClientSharedMemory2_C_API.cpp",
+ "../SharedMemory/PhysicsClientSharedMemory2_C_API.h",
+ "../SharedMemory/SharedMemoryCommandProcessor.cpp",
+ "../SharedMemory/SharedMemoryCommandProcessor.h",
"../SharedMemory/SharedMemoryInProcessPhysicsC_API.cpp",
"../SharedMemory/PhysicsClient.cpp",
"../SharedMemory/PosixSharedMemory.cpp",
@@ -95,7 +103,8 @@ project "App_BulletExampleBrowser"
"../RoboticsLearning/*",
"../Collision/Internal/*",
"../Benchmarks/*",
- "../CommonInterfaces/*",
+ "../MultiThreadedDemo/*",
+ "../CommonInterfaces/*.h",
"../ForkLift/ForkLiftDemo.*",
"../Importers/**",
"../../Extras/Serialize/BulletWorldImporter/*",
diff --git a/examples/ExtendedTutorials/InclinedPlane.cpp b/examples/ExtendedTutorials/InclinedPlane.cpp
index dceafdbe8..2c36f8ffa 100644
--- a/examples/ExtendedTutorials/InclinedPlane.cpp
+++ b/examples/ExtendedTutorials/InclinedPlane.cpp
@@ -69,19 +69,19 @@ struct InclinedPlaneExample : public CommonRigidBodyBase
};
-void onBoxFrictionChanged(float friction);
+void onBoxFrictionChanged(float friction, void* userPtr);
-void onBoxRestitutionChanged(float restitution);
+void onBoxRestitutionChanged(float restitution, void* userPtr);
-void onSphereFrictionChanged(float friction);
+void onSphereFrictionChanged(float friction, void* userPtr);
-void onSphereRestitutionChanged(float restitution);
+void onSphereRestitutionChanged(float restitution, void* userPtr);
-void onRampInclinationChanged(float inclination);
+void onRampInclinationChanged(float inclination, void* userPtr);
-void onRampFrictionChanged(float friction);
+void onRampFrictionChanged(float friction, void* userPtr);
-void onRampRestitutionChanged(float restitution);
+void onRampRestitutionChanged(float restitution, void* userPtr);
void InclinedPlaneExample::initPhysics()
{
@@ -306,35 +306,35 @@ bool InclinedPlaneExample::keyboardCallback(int key, int state) {
// GUI parameter modifiers
-void onBoxFrictionChanged(float friction){
+void onBoxFrictionChanged(float friction, void*){
if(gBox){
gBox->setFriction(friction);
// b3Printf("Friction of box changed to %f",friction );
}
}
-void onBoxRestitutionChanged(float restitution){
+void onBoxRestitutionChanged(float restitution, void*){
if(gBox){
gBox->setRestitution(restitution);
//b3Printf("Restitution of box changed to %f",restitution);
}
}
-void onSphereFrictionChanged(float friction){
+void onSphereFrictionChanged(float friction, void*){
if(gSphere){
gSphere->setFriction(friction);
//b3Printf("Friction of sphere changed to %f",friction );
}
}
-void onSphereRestitutionChanged(float restitution){
+void onSphereRestitutionChanged(float restitution, void*){
if(gSphere){
gSphere->setRestitution(restitution);
//b3Printf("Restitution of sphere changed to %f",restitution);
}
}
-void onRampInclinationChanged(float inclination){
+void onRampInclinationChanged(float inclination, void*){
if(ramp){
btTransform startTransform;
startTransform.setIdentity();
@@ -351,14 +351,14 @@ void onRampInclinationChanged(float inclination){
}
}
-void onRampFrictionChanged(float friction){
+void onRampFrictionChanged(float friction, void*){
if(ramp){
ramp->setFriction(friction);
//b3Printf("Friction of ramp changed to %f \n",friction );
}
}
-void onRampRestitutionChanged(float restitution){
+void onRampRestitutionChanged(float restitution, void*){
if(ramp){
ramp->setRestitution(restitution);
//b3Printf("Restitution of ramp changed to %f \n",restitution);
diff --git a/examples/ExtendedTutorials/MultiPendulum.cpp b/examples/ExtendedTutorials/MultiPendulum.cpp
index 038aab3ec..b45eee755 100644
--- a/examples/ExtendedTutorials/MultiPendulum.cpp
+++ b/examples/ExtendedTutorials/MultiPendulum.cpp
@@ -71,11 +71,9 @@ struct MultiPendulumExample: public CommonRigidBodyBase {
static MultiPendulumExample* mex = NULL; // Handle to the example to access it via functions. Do not use this in your simulation!
-void onMultiPendulaLengthChanged(float pendulaLength); // Change the pendula length
+void onMultiPendulaLengthChanged(float pendulaLength, void*); // Change the pendula length
-void onMultiPendulaRestitutionChanged(float pendulaRestitution); // change the pendula restitution
-
-void floorMSliderValue(float notUsed); // floor the slider values which should be integers
+void onMultiPendulaRestitutionChanged(float pendulaRestitution, void*); // change the pendula restitution
void applyMForceWithForceScalar(float forceScalar);
@@ -85,8 +83,7 @@ void MultiPendulumExample::initPhysics() { // Setup your physics scene
SliderParams slider("Number of Pendula", &gPendulaQty);
slider.m_minVal = 1;
slider.m_maxVal = 50;
- slider.m_callback = floorMSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -95,8 +92,7 @@ void MultiPendulumExample::initPhysics() { // Setup your physics scene
SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula);
slider.m_minVal = 0;
slider.m_maxVal = 49;
- slider.m_callback = floorMSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -397,7 +393,7 @@ void MultiPendulumExample::applyPendulumForce(btScalar pendulumForce){
// GUI parameter modifiers
-void onMultiPendulaLengthChanged(float pendulaLength) { // Change the pendula length
+void onMultiPendulaLengthChanged(float pendulaLength, void*) { // Change the pendula length
if (mex){
mex->changePendulaLength(pendulaLength);
}
@@ -405,18 +401,13 @@ void onMultiPendulaLengthChanged(float pendulaLength) { // Change the pendula le
}
-void onMultiPendulaRestitutionChanged(float pendulaRestitution) { // change the pendula restitution
+void onMultiPendulaRestitutionChanged(float pendulaRestitution, void*) { // change the pendula restitution
if (mex){
mex->changePendulaRestitution(pendulaRestitution);
}
}
-void floorMSliderValue(float notUsed) { // floor the slider values which should be integers
- gPendulaQty = floor(gPendulaQty);
- gDisplacedPendula = floor(gDisplacedPendula);
-}
-
void applyMForceWithForceScalar(float forceScalar) {
if(mex){
btScalar appliedForce = forceScalar * gDisplacementForce;
diff --git a/examples/ExtendedTutorials/NewtonsCradle.cpp b/examples/ExtendedTutorials/NewtonsCradle.cpp
index 0d4c52095..54be8367a 100644
--- a/examples/ExtendedTutorials/NewtonsCradle.cpp
+++ b/examples/ExtendedTutorials/NewtonsCradle.cpp
@@ -71,11 +71,9 @@ struct NewtonsCradleExample: public CommonRigidBodyBase {
static NewtonsCradleExample* nex = NULL;
-void onPendulaLengthChanged(float pendulaLength); // Change the pendula length
+void onPendulaLengthChanged(float pendulaLength, void* userPtr); // Change the pendula length
-void onPendulaRestitutionChanged(float pendulaRestitution); // change the pendula restitution
-
-void floorSliderValue(float notUsed); // floor the slider values which should be integers
+void onPendulaRestitutionChanged(float pendulaRestitution, void* userPtr); // change the pendula restitution
void applyForceWithForceScalar(float forceScalar);
@@ -85,8 +83,7 @@ void NewtonsCradleExample::initPhysics() {
SliderParams slider("Number of Pendula", &gPendulaQty);
slider.m_minVal = 1;
slider.m_maxVal = 50;
- slider.m_callback = floorSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -95,8 +92,7 @@ void NewtonsCradleExample::initPhysics() {
SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula);
slider.m_minVal = 0;
slider.m_maxVal = 49;
- slider.m_callback = floorSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -343,25 +339,19 @@ void NewtonsCradleExample::applyPendulumForce(btScalar pendulumForce){
// GUI parameter modifiers
-void onPendulaLengthChanged(float pendulaLength) {
+void onPendulaLengthChanged(float pendulaLength, void*) {
if (nex){
nex->changePendulaLength(pendulaLength);
//b3Printf("Pendula length changed to %f \n",sliderValue );
}
}
-void onPendulaRestitutionChanged(float pendulaRestitution) {
+void onPendulaRestitutionChanged(float pendulaRestitution, void*) {
if (nex){
nex->changePendulaRestitution(pendulaRestitution);
}
}
-void floorSliderValue(float notUsed) {
- gPendulaQty = floor(gPendulaQty);
- gDisplacedPendula = floor(gDisplacedPendula);
-
-}
-
void applyForceWithForceScalar(float forceScalar) {
if(nex){
btScalar appliedForce = forceScalar * gDisplacementForce;
diff --git a/examples/ExtendedTutorials/NewtonsRopeCradle.cpp b/examples/ExtendedTutorials/NewtonsRopeCradle.cpp
index 94c96a71f..76eb115ea 100644
--- a/examples/ExtendedTutorials/NewtonsRopeCradle.cpp
+++ b/examples/ExtendedTutorials/NewtonsRopeCradle.cpp
@@ -105,9 +105,7 @@ struct NewtonsRopeCradleExample : public CommonRigidBodyBase {
static NewtonsRopeCradleExample* nex = NULL;
-void onRopePendulaRestitutionChanged(float pendulaRestitution);
-
-void floorRSliderValue(float notUsed);
+void onRopePendulaRestitutionChanged(float pendulaRestitution, void*);
void applyRForceWithForceScalar(float forceScalar);
@@ -118,8 +116,7 @@ void NewtonsRopeCradleExample::initPhysics()
SliderParams slider("Number of Pendula", &gPendulaQty);
slider.m_minVal = 1;
slider.m_maxVal = 50;
- slider.m_callback = floorRSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -128,8 +125,7 @@ void NewtonsRopeCradleExample::initPhysics()
SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula);
slider.m_minVal = 0;
slider.m_maxVal = 49;
- slider.m_callback = floorRSliderValue; // hack to get integer values
- slider.m_clampToNotches = false;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -148,8 +144,7 @@ void NewtonsRopeCradleExample::initPhysics()
SliderParams slider("Rope Resolution", &gRopeResolution);
slider.m_minVal = 1;
slider.m_maxVal = 20;
- slider.m_clampToNotches = false;
- slider.m_callback = floorRSliderValue;
+ slider.m_clampToIntegers = true;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider);
}
@@ -357,18 +352,12 @@ void NewtonsRopeCradleExample::applyPendulumForce(btScalar pendulumForce){
// GUI parameter modifiers
-void onRopePendulaRestitutionChanged(float pendulaRestitution) {
+void onRopePendulaRestitutionChanged(float pendulaRestitution, void*) {
if (nex){
nex->changePendulaRestitution(pendulaRestitution);
}
}
-void floorRSliderValue(float notUsed) {
- gPendulaQty = floor(gPendulaQty);
- gDisplacedPendula = floor(gDisplacedPendula);
- gRopeResolution = floor(gRopeResolution);
-}
-
void applyRForceWithForceScalar(float forceScalar) {
if(nex){
btScalar appliedForce = forceScalar * gDisplacementForce;
diff --git a/examples/ExtendedTutorials/premake4.lua b/examples/ExtendedTutorials/premake4.lua
index 41126e0af..bbfa7c224 100644
--- a/examples/ExtendedTutorials/premake4.lua
+++ b/examples/ExtendedTutorials/premake4.lua
@@ -17,6 +17,7 @@ language "C++"
files {
"RigidBodyFromObj.cpp",
+ "../CommonInterfaces/*",
"**.h",
"../StandaloneMain/main_console_single_example.cpp",
"../Utils/b3ResourcePath.cpp",
@@ -68,6 +69,7 @@ files {
"RigidBodyFromObj.cpp",
"*.h",
"../StandaloneMain/main_opengl_single_example.cpp",
+ "../CommonInterfaces/*",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
@@ -132,6 +134,7 @@ files {
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
+ "../CommonInterfaces/*",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
"../TinyRenderer/tgaimage.cpp",
@@ -193,6 +196,7 @@ files {
"../StandaloneMain/main_tinyrenderer_single_example.cpp",
"../OpenGLWindow/SimpleCamera.cpp",
"../ExampleBrowser/CollisionShape2TriangleMesh.cpp",
+ "../CommonInterfaces/*",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
"../TinyRenderer/tgaimage.cpp",
diff --git a/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.cpp b/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.cpp
new file mode 100644
index 000000000..f4259f77e
--- /dev/null
+++ b/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.cpp
@@ -0,0 +1,236 @@
+
+#include "ImportMJCFSetup.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+//#define TEST_MULTIBODY_SERIALIZATION 1
+
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "Bullet3Common/b3FileUtils.h"
+
+#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "../CommonInterfaces/CommonParameterInterface.h"
+#include "../../Utils/b3ResourcePath.h"
+
+#include "../CommonInterfaces/CommonMultiBodyBase.h"
+
+#include "../ImportURDFDemo/MyMultiBodyCreator.h"
+
+class ImportMJCFSetup : public CommonMultiBodyBase
+{
+ char m_fileName[1024];
+
+ struct ImportMJCFInternalData* m_data;
+ bool m_useMultiBody;
+ btAlignedObjectArray m_nameMemory;
+ btScalar m_grav;
+ int m_upAxis;
+public:
+ ImportMJCFSetup(struct GUIHelperInterface* helper, int option, const char* fileName);
+ virtual ~ImportMJCFSetup();
+
+ virtual void initPhysics();
+ virtual void stepSimulation(float deltaTime);
+
+ void setFileName(const char* mjcfFileName);
+
+ virtual void resetCamera()
+ {
+ float dist = 3.5;
+ float pitch = -136;
+ float yaw = 28;
+ float targetPos[3]={0.47,0,-0.64};
+ m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
+ }
+};
+
+
+static btAlignedObjectArray gMCFJFileNameArray;
+
+
+#define MAX_NUM_MOTORS 1024
+
+struct ImportMJCFInternalData
+{
+ ImportMJCFInternalData()
+ :m_numMotors(0),
+ m_mb(0)
+ {
+ for (int i=0;i=numFileNames)
+ {
+ count=0;
+ }
+ sprintf(m_fileName,"%s",gMCFJFileNameArray[count++].c_str());
+ }
+}
+
+ImportMJCFSetup::~ImportMJCFSetup()
+{
+ for (int i=0;isetUpAxis(m_upAxis);
+
+ this->createEmptyDynamicsWorld();
+ //m_dynamicsWorld->getSolverInfo().m_numIterations = 100;
+ m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
+ m_dynamicsWorld->getDebugDrawer()->setDebugMode(
+ btIDebugDraw::DBG_DrawConstraints
+ +btIDebugDraw::DBG_DrawContactPoints
+ +btIDebugDraw::DBG_DrawAabb
+ );//+btIDebugDraw::DBG_DrawConstraintLimits);
+
+
+ if (m_guiHelper->getParameterInterface())
+ {
+ SliderParams slider("Gravity", &m_grav);
+ slider.m_minVal = -10;
+ slider.m_maxVal = 10;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
+ }
+
+
+
+}
+
+
+
+void ImportMJCFSetup::stepSimulation(float deltaTime)
+{
+ if (m_dynamicsWorld)
+ {
+ btVector3 gravity(0, 0, 0);
+ gravity[m_upAxis] = m_grav;
+ m_dynamicsWorld->setGravity(gravity);
+
+ for (int i=0;im_numMotors;i++)
+ {
+ if (m_data->m_jointMotors[i])
+ {
+ m_data->m_jointMotors[i]->setVelocityTarget(m_data->m_motorTargetVelocities[i]);
+ }
+ if (m_data->m_generic6DofJointMotors[i])
+ {
+ GenericConstraintUserInfo* jointInfo = (GenericConstraintUserInfo*)m_data->m_generic6DofJointMotors[i]->getUserConstraintPtr();
+ m_data->m_generic6DofJointMotors[i]->setTargetVelocity(jointInfo->m_jointAxisIndex,m_data->m_motorTargetVelocities[i]);
+ //jointInfo->
+ }
+ }
+
+ //the maximal coordinates/iterative MLCP solver requires a smallish timestep to converge
+ m_dynamicsWorld->stepSimulation(deltaTime,10,1./240.);
+ }
+}
+
+class CommonExampleInterface* ImportMJCFCreateFunc(struct CommonExampleOptions& options)
+{
+
+ return new ImportMJCFSetup(options.m_guiHelper, options.m_option,options.m_fileName);
+}
diff --git a/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.h b/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.h
new file mode 100644
index 000000000..52b399426
--- /dev/null
+++ b/examples/Importers/ImportMJCFDemo/ImportMJCFSetup.h
@@ -0,0 +1,8 @@
+#ifndef IMPORT_MJCF_SETUP_H
+#define IMPORT_MJCF_SETUP_H
+
+
+class CommonExampleInterface* ImportMJCFCreateFunc(struct CommonExampleOptions& options);
+
+
+#endif //IMPORT_MJCF_SETUP_H
diff --git a/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp b/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp
index 3dfe17dd0..aba0b3e03 100644
--- a/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp
+++ b/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp
@@ -135,7 +135,7 @@ ImportUrdfSetup::ImportUrdfSetup(struct GUIHelperInterface* helper, int option,
if (gFileNameArray.size()==0)
{
- gFileNameArray.push_back("r2d2.urdf");
+ gFileNameArray.push_back("quadruped/quadruped.urdf");
}
diff --git a/examples/Importers/ImportURDFDemo/URDF2Bullet.cpp b/examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
index d9e58ef5a..7c0f2c86a 100644
--- a/examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
+++ b/examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
@@ -143,6 +143,34 @@ void InitURDF2BulletCache(const URDFImporterInterface& u2b, URDF2BulletCachedDat
}
+void processContactParameters(const URDFLinkContactInfo& contactInfo, btCollisionObject* col)
+{
+ if ((contactInfo.m_flags & URDF_CONTACT_HAS_LATERAL_FRICTION) != 0)
+ {
+ col->setFriction(contactInfo.m_lateralFriction);
+ }
+ if ((contactInfo.m_flags & URDF_CONTACT_HAS_RESTITUTION) != 0)
+ {
+ col->setRestitution(contactInfo.m_restitution);
+ }
+
+ if ((contactInfo.m_flags & URDF_CONTACT_HAS_ROLLING_FRICTION) != 0)
+ {
+ col->setRollingFriction(contactInfo.m_rollingFriction);
+ }
+ if ((contactInfo.m_flags & URDF_CONTACT_HAS_SPINNING_FRICTION) != 0)
+ {
+ col->setSpinningFriction(contactInfo.m_spinningFriction);
+ }
+ if ((contactInfo.m_flags & URDF_CONTACT_HAS_STIFFNESS_DAMPING) != 0)
+ {
+ col->setContactStiffnessAndDamping(contactInfo.m_contactStiffness, contactInfo.m_contactDamping);
+ }
+}
+
+
+
+
void ConvertURDF2BulletInternal(
const URDFImporterInterface& u2b, MultiBodyCreationInterface& creation,
URDF2BulletCachedData& cache, int urdfLinkIndex,
@@ -258,11 +286,18 @@ void ConvertURDF2BulletInternal(
world1->addRigidBody(body);
+
compoundShape->setUserIndex(graphicsIndex);
+ URDFLinkContactInfo contactInfo;
+ u2b.getLinkContactInfo(urdfLinkIndex, contactInfo);
+
+ processContactParameters(contactInfo, body);
creation.createRigidBodyGraphicsInstance(urdfLinkIndex, body, color, graphicsIndex);
cache.registerRigidBody(urdfLinkIndex, body, inertialFrameInWorldSpace, mass, localInertiaDiagonal, compoundShape, localInertialFrame);
+
+
//untested: u2b.convertLinkVisualShapes2(urdfLinkIndex,pathPrefix,localInertialFrame,body);
} else
{
@@ -413,22 +448,7 @@ void ConvertURDF2BulletInternal(
URDFLinkContactInfo contactInfo;
u2b.getLinkContactInfo(urdfLinkIndex,contactInfo);
- if ((contactInfo.m_flags & URDF_CONTACT_HAS_LATERAL_FRICTION)!=0)
- {
- col->setFriction(contactInfo.m_lateralFriction);
- }
- if ((contactInfo.m_flags & URDF_CONTACT_HAS_ROLLING_FRICTION)!=0)
- {
- col->setRollingFriction(contactInfo.m_rollingFriction);
- }
- if ((contactInfo.m_flags & URDF_CONTACT_HAS_SPINNING_FRICTION)!=0)
- {
- col->setSpinningFriction(contactInfo.m_spinningFriction);
- }
- if ((contactInfo.m_flags & URDF_CONTACT_HAS_STIFFNESS_DAMPING)!=0)
- {
- col->setContactStiffnessAndDamping(contactInfo.m_contactStiffness,contactInfo.m_contactDamping);
- }
+ processContactParameters(contactInfo, col);
if (mbLinkIndex>=0) //???? double-check +/- 1
{
diff --git a/examples/Importers/ImportURDFDemo/URDFJointTypes.h b/examples/Importers/ImportURDFDemo/URDFJointTypes.h
index 88912cb1a..2bcb53214 100644
--- a/examples/Importers/ImportURDFDemo/URDFJointTypes.h
+++ b/examples/Importers/ImportURDFDemo/URDFJointTypes.h
@@ -22,6 +22,7 @@ enum URDF_LinkContactFlags
URDF_CONTACT_HAS_STIFFNESS_DAMPING=16,
URDF_CONTACT_HAS_ROLLING_FRICTION=32,
URDF_CONTACT_HAS_SPINNING_FRICTION=64,
+ URDF_CONTACT_HAS_RESTITUTION=128,
};
@@ -30,6 +31,7 @@ struct URDFLinkContactInfo
btScalar m_lateralFriction;
btScalar m_rollingFriction;
btScalar m_spinningFriction;
+ btScalar m_restitution;
btScalar m_inertiaScaling;
btScalar m_contactCfm;
btScalar m_contactErp;
@@ -42,6 +44,7 @@ struct URDFLinkContactInfo
:m_lateralFriction(0.5),
m_rollingFriction(0),
m_spinningFriction(0),
+ m_restitution(0),
m_inertiaScaling(1),
m_contactCfm(0),
m_contactErp(0),
diff --git a/examples/Importers/ImportURDFDemo/UrdfParser.cpp b/examples/Importers/ImportURDFDemo/UrdfParser.cpp
index 817cb0ce5..bcac5eec7 100644
--- a/examples/Importers/ImportURDFDemo/UrdfParser.cpp
+++ b/examples/Importers/ImportURDFDemo/UrdfParser.cpp
@@ -672,6 +672,31 @@ bool UrdfParser::parseLink(UrdfModel& model, UrdfLink& link, TiXmlElement *confi
}
}
}
+
+ {
+ TiXmlElement *restitution_xml = ci->FirstChildElement("restitution");
+ if (restitution_xml)
+ {
+ if (m_parseSDF)
+ {
+ link.m_contactInfo.m_restitution = urdfLexicalCast(restitution_xml->GetText());
+ link.m_contactInfo.m_flags |= URDF_CONTACT_HAS_RESTITUTION;
+ }
+ else
+ {
+ if (!restitution_xml->Attribute("value"))
+ {
+ logger->reportError("Link/contact: restitution element must have value attribute");
+ return false;
+ }
+
+ link.m_contactInfo.m_restitution = urdfLexicalCast(restitution_xml->Attribute("value"));
+ link.m_contactInfo.m_flags |= URDF_CONTACT_HAS_RESTITUTION;
+
+ }
+ }
+ }
+
{
TiXmlElement *spinning_xml = ci->FirstChildElement("spinning_friction");
if (spinning_xml)
diff --git a/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp
new file mode 100644
index 000000000..8375489ee
--- /dev/null
+++ b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp
@@ -0,0 +1,868 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#include
+#include
+
+class btCollisionShape;
+
+#include "CommonRigidBodyMTBase.h"
+#include "../CommonInterfaces/CommonParameterInterface.h"
+#include "ParallelFor.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "btBulletCollisionCommon.h"
+#include "BulletDynamics/Dynamics/btSimulationIslandManagerMt.h" // for setSplitIslands()
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+
+TaskManager gTaskMgr;
+
+#define USE_PARALLEL_NARROWPHASE 1 // detect collisions in parallel
+#define USE_PARALLEL_ISLAND_SOLVER 1 // solve simulation islands in parallel
+#define USE_PARALLEL_CREATE_PREDICTIVE_CONTACTS 1
+#define USE_PARALLEL_INTEGRATE_TRANSFORMS 1
+#define USE_PARALLEL_PREDICT_UNCONSTRAINED_MOTION 1
+
+#if defined (_MSC_VER) && _MSC_VER >= 1600
+// give us a compile error if any signatures of overriden methods is changed
+#define BT_OVERRIDE override
+#else
+#define BT_OVERRIDE
+#endif
+
+
+class Profiler
+{
+public:
+ enum RecordType
+ {
+ kRecordInternalTimeStep,
+ kRecordDispatchAllCollisionPairs,
+ kRecordDispatchIslands,
+ kRecordPredictUnconstrainedMotion,
+ kRecordCreatePredictiveContacts,
+ kRecordIntegrateTransforms,
+ kRecordCount
+ };
+
+private:
+ btClock mClock;
+
+ struct Record
+ {
+ int mCallCount;
+ unsigned long long mAccum;
+ unsigned int mStartTime;
+ unsigned int mHistory[8];
+
+ void begin(unsigned int curTime)
+ {
+ mStartTime = curTime;
+ }
+ void end(unsigned int curTime)
+ {
+ unsigned int endTime = curTime;
+ unsigned int elapsed = endTime - mStartTime;
+ mAccum += elapsed;
+ mHistory[ mCallCount & 7 ] = elapsed;
+ ++mCallCount;
+ }
+ float getAverageTime() const
+ {
+ int count = btMin( 8, mCallCount );
+ if ( count > 0 )
+ {
+ unsigned int sum = 0;
+ for ( int i = 0; i < count; ++i )
+ {
+ sum += mHistory[ i ];
+ }
+ float avg = float( sum ) / float( count );
+ return avg;
+ }
+ return 0.0;
+ }
+ };
+ Record mRecords[ kRecordCount ];
+
+public:
+ void begin(RecordType rt)
+ {
+ mRecords[rt].begin(mClock.getTimeMicroseconds());
+ }
+ void end(RecordType rt)
+ {
+ mRecords[rt].end(mClock.getTimeMicroseconds());
+ }
+ float getAverageTime(RecordType rt) const
+ {
+ return mRecords[rt].getAverageTime();
+ }
+};
+
+
+Profiler gProfiler;
+
+class ProfileHelper
+{
+ Profiler::RecordType mRecType;
+public:
+ ProfileHelper(Profiler::RecordType rt)
+ {
+ mRecType = rt;
+ gProfiler.begin( mRecType );
+ }
+ ~ProfileHelper()
+ {
+ gProfiler.end( mRecType );
+ }
+};
+
+int gThreadsRunningCounter = 0;
+btSpinMutex gThreadsRunningCounterMutex;
+
+void btPushThreadsAreRunning()
+{
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter++;
+ gThreadsRunningCounterMutex.unlock();
+}
+
+void btPopThreadsAreRunning()
+{
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter--;
+ gThreadsRunningCounterMutex.unlock();
+}
+
+bool btThreadsAreRunning()
+{
+ return gThreadsRunningCounter != 0;
+}
+
+
+#if USE_PARALLEL_NARROWPHASE
+
+class MyCollisionDispatcher : public btCollisionDispatcher
+{
+ btSpinMutex m_manifoldPtrsMutex;
+
+public:
+ MyCollisionDispatcher( btCollisionConfiguration* config ) : btCollisionDispatcher( config )
+ {
+ }
+
+ virtual ~MyCollisionDispatcher()
+ {
+ }
+
+ btPersistentManifold* getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 ) BT_OVERRIDE
+ {
+ // added spin-locks
+ //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+ btScalar contactBreakingThreshold = ( m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD ) ?
+ btMin( body0->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ), body1->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ) )
+ : gContactBreakingThreshold;
+
+ btScalar contactProcessingThreshold = btMin( body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold() );
+
+ void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
+ if (NULL == mem)
+ {
+ //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+ if ( ( m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION ) == 0 )
+ {
+ mem = btAlignedAlloc( sizeof( btPersistentManifold ), 16 );
+ }
+ else
+ {
+ btAssert( 0 );
+ //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+ return 0;
+ }
+ }
+ btPersistentManifold* manifold = new(mem) btPersistentManifold( body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold );
+ m_manifoldPtrsMutex.lock();
+ manifold->m_index1a = m_manifoldsPtr.size();
+ m_manifoldsPtr.push_back( manifold );
+ m_manifoldPtrsMutex.unlock();
+
+ return manifold;
+ }
+
+ void releaseManifold( btPersistentManifold* manifold ) BT_OVERRIDE
+ {
+ clearManifold( manifold );
+
+ m_manifoldPtrsMutex.lock();
+ int findIndex = manifold->m_index1a;
+ btAssert( findIndex < m_manifoldsPtr.size() );
+ m_manifoldsPtr.swap( findIndex, m_manifoldsPtr.size() - 1 );
+ m_manifoldsPtr[ findIndex ]->m_index1a = findIndex;
+ m_manifoldsPtr.pop_back();
+ m_manifoldPtrsMutex.unlock();
+
+ manifold->~btPersistentManifold();
+ if ( m_persistentManifoldPoolAllocator->validPtr( manifold ) )
+ {
+ m_persistentManifoldPoolAllocator->freeMemory( manifold );
+ }
+ else
+ {
+ btAlignedFree( manifold );
+ }
+ }
+
+ struct Updater
+ {
+ btBroadphasePair* mPairArray;
+ btNearCallback mCallback;
+ btCollisionDispatcher* mDispatcher;
+ const btDispatcherInfo* mInfo;
+
+ Updater()
+ {
+ mPairArray = NULL;
+ mCallback = NULL;
+ mDispatcher = NULL;
+ mInfo = NULL;
+ }
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btBroadphasePair* pair = &mPairArray[ i ];
+ mCallback( *pair, *mDispatcher, *mInfo );
+ }
+ }
+ };
+
+ virtual void dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher ) BT_OVERRIDE
+ {
+ ProfileHelper prof(Profiler::kRecordDispatchAllCollisionPairs);
+ int grainSize = 40; // iterations per task
+ int pairCount = pairCache->getNumOverlappingPairs();
+ Updater updater;
+ updater.mCallback = getNearCallback();
+ updater.mPairArray = pairCount > 0 ? pairCache->getOverlappingPairArrayPtr() : NULL;
+ updater.mDispatcher = this;
+ updater.mInfo = &info;
+
+ btPushThreadsAreRunning();
+ parallelFor( 0, pairCount, grainSize, updater );
+ btPopThreadsAreRunning();
+
+ if (m_manifoldsPtr.size() < 1)
+ return;
+
+ // reconstruct the manifolds array to ensure determinism
+ m_manifoldsPtr.resizeNoInitialize(0);
+ btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
+ for (int i = 0; i < pairCount; ++i)
+ {
+ btCollisionAlgorithm* algo = pairs[i].m_algorithm;
+ if (algo) algo->getAllContactManifolds(m_manifoldsPtr);
+ }
+
+ // update the indices (used when releasing manifolds)
+ for (int i = 0; i < m_manifoldsPtr.size(); ++i)
+ m_manifoldsPtr[i]->m_index1a = i;
+ }
+};
+
+#endif
+
+
+#if USE_PARALLEL_ISLAND_SOLVER
+///
+/// MyConstraintSolverPool - masquerades as a constraint solver, but really it is a threadsafe pool of them.
+///
+/// Each solver in the pool is protected by a mutex. When solveGroup is called from a thread,
+/// the pool looks for a solver that isn't being used by another thread, locks it, and dispatches the
+/// call to the solver.
+/// So long as there are at least as many solvers as there are hardware threads, it should never need to
+/// spin wait.
+///
+class MyConstraintSolverPool : public btConstraintSolver
+{
+ const static size_t kCacheLineSize = 128;
+ struct ThreadSolver
+ {
+ btConstraintSolver* solver;
+ btSpinMutex mutex;
+ char _cachelinePadding[ kCacheLineSize - sizeof( btSpinMutex ) - sizeof( void* ) ]; // keep mutexes from sharing a cache line
+ };
+ btAlignedObjectArray m_solvers;
+ btConstraintSolverType m_solverType;
+
+ ThreadSolver* getAndLockThreadSolver()
+ {
+ while ( true )
+ {
+ for ( int i = 0; i < m_solvers.size(); ++i )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ if ( solver.mutex.tryLock() )
+ {
+ return &solver;
+ }
+ }
+ }
+ return NULL;
+ }
+ void init( btConstraintSolver** solvers, int numSolvers )
+ {
+ m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
+ m_solvers.resize( numSolvers );
+ for ( int i = 0; i < numSolvers; ++i )
+ {
+ m_solvers[ i ].solver = solvers[ i ];
+ }
+ if ( numSolvers > 0 )
+ {
+ m_solverType = solvers[ 0 ]->getSolverType();
+ }
+ }
+public:
+ // create the solvers for me
+ explicit MyConstraintSolverPool( int numSolvers )
+ {
+ btAlignedObjectArray solvers;
+ solvers.reserve( numSolvers );
+ for ( int i = 0; i < numSolvers; ++i )
+ {
+ btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
+ solvers.push_back( solver );
+ }
+ init( &solvers[ 0 ], numSolvers );
+ }
+
+ // pass in fully constructed solvers (destructor will delete them)
+ MyConstraintSolverPool( btConstraintSolver** solvers, int numSolvers )
+ {
+ init( solvers, numSolvers );
+ }
+ virtual ~MyConstraintSolverPool()
+ {
+ // delete all solvers
+ for ( int i = 0; i < m_solvers.size(); ++i )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ delete solver.solver;
+ solver.solver = NULL;
+ }
+ }
+
+ //virtual void prepareSolve( int /* numBodies */, int /* numManifolds */ ) { ; } // does nothing
+
+ ///solve a group of constraints
+ virtual btScalar solveGroup( btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& info,
+ btIDebugDraw* debugDrawer,
+ btDispatcher* dispatcher
+ )
+ {
+ ThreadSolver* solver = getAndLockThreadSolver();
+ solver->solver->solveGroup( bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher );
+ solver->mutex.unlock();
+ return 0.0f;
+ }
+
+ //virtual void allSolved( const btContactSolverInfo& /* info */, class btIDebugDraw* /* debugDrawer */ ) { ; } // does nothing
+
+ ///clear internal cached data and reset random seed
+ virtual void reset()
+ {
+ for ( int i = 0; i < m_solvers.size(); ++i )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ solver.mutex.lock();
+ solver.solver->reset();
+ solver.mutex.unlock();
+ }
+ }
+
+ virtual btConstraintSolverType getSolverType() const
+ {
+ return m_solverType;
+ }
+};
+
+struct UpdateIslandDispatcher
+{
+ btAlignedObjectArray* islandsPtr;
+ btSimulationIslandManagerMt::IslandCallback* callback;
+
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ i ];
+ btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL;
+ btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL;
+ callback->processIsland( &island->bodyArray[ 0 ],
+ island->bodyArray.size(),
+ manifolds,
+ island->manifoldArray.size(),
+ constraintsPtr,
+ island->constraintArray.size(),
+ island->id
+ );
+ }
+ }
+};
+
+static int gNumIslands = 0;
+
+void parallelIslandDispatch( btAlignedObjectArray* islandsPtr, btSimulationIslandManagerMt::IslandCallback* callback )
+{
+ ProfileHelper prof(Profiler::kRecordDispatchIslands);
+ gNumIslands = islandsPtr->size();
+ int grainSize = 1; // iterations per task
+ UpdateIslandDispatcher dispatcher;
+ dispatcher.islandsPtr = islandsPtr;
+ dispatcher.callback = callback;
+ btPushThreadsAreRunning();
+ parallelFor( 0, islandsPtr->size(), grainSize, dispatcher );
+ btPopThreadsAreRunning();
+}
+#endif //#if USE_PARALLEL_ISLAND_SOLVER
+
+
+void profileBeginCallback(btDynamicsWorld *world, btScalar timeStep)
+{
+ gProfiler.begin(Profiler::kRecordInternalTimeStep);
+}
+
+void profileEndCallback(btDynamicsWorld *world, btScalar timeStep)
+{
+ gProfiler.end(Profiler::kRecordInternalTimeStep);
+}
+
+///
+/// MyDiscreteDynamicsWorld
+///
+/// Should function exactly like btDiscreteDynamicsWorld.
+/// 3 methods that iterate over all of the rigidbodies can run in parallel:
+/// - predictUnconstraintMotion
+/// - integrateTransforms
+/// - createPredictiveContacts
+///
+ATTRIBUTE_ALIGNED16( class ) MyDiscreteDynamicsWorld : public btDiscreteDynamicsWorldMt
+{
+ typedef btDiscreteDynamicsWorld ParentClass;
+
+protected:
+#if USE_PARALLEL_PREDICT_UNCONSTRAINED_MOTION
+ struct UpdaterUnconstrainedMotion
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btRigidBody* body = rigidBodies[ i ];
+ if ( !body->isStaticOrKinematicObject() )
+ {
+ //don't integrate/update velocities here, it happens in the constraint solver
+ body->applyDamping( timeStep );
+ body->predictIntegratedTransform( timeStep, body->getInterpolationWorldTransform() );
+ }
+ }
+ }
+ };
+
+ virtual void predictUnconstraintMotion( btScalar timeStep ) BT_OVERRIDE
+ {
+ ProfileHelper prof( Profiler::kRecordPredictUnconstrainedMotion );
+ BT_PROFILE( "predictUnconstraintMotion" );
+ int grainSize = 50; // num of iterations per task for TBB
+ int bodyCount = m_nonStaticRigidBodies.size();
+ UpdaterUnconstrainedMotion update;
+ update.timeStep = timeStep;
+ update.rigidBodies = bodyCount ? &m_nonStaticRigidBodies[ 0 ] : NULL;
+ btPushThreadsAreRunning();
+ parallelFor( 0, bodyCount, grainSize, update );
+ btPopThreadsAreRunning();
+ }
+#endif // #if USE_PARALLEL_PREDICT_UNCONSTRAINED_MOTION
+
+#if USE_PARALLEL_CREATE_PREDICTIVE_CONTACTS
+ struct UpdaterCreatePredictiveContacts
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ MyDiscreteDynamicsWorld* world;
+
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ world->createPredictiveContactsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
+ }
+ };
+
+ virtual void createPredictiveContacts( btScalar timeStep )
+ {
+ ProfileHelper prof( Profiler::kRecordCreatePredictiveContacts );
+ releasePredictiveContacts();
+ int grainSize = 50; // num of iterations per task for TBB or OPENMP
+ if ( int bodyCount = m_nonStaticRigidBodies.size() )
+ {
+ UpdaterCreatePredictiveContacts update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
+ btPushThreadsAreRunning();
+ parallelFor( 0, bodyCount, grainSize, update );
+ btPopThreadsAreRunning();
+ }
+ }
+#endif // #if USE_PARALLEL_CREATE_PREDICTIVE_CONTACTS
+
+#if USE_PARALLEL_INTEGRATE_TRANSFORMS
+ struct UpdaterIntegrateTransforms
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ MyDiscreteDynamicsWorld* world;
+
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ world->integrateTransformsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
+ }
+ };
+
+ virtual void integrateTransforms( btScalar timeStep ) BT_OVERRIDE
+ {
+ ProfileHelper prof( Profiler::kRecordIntegrateTransforms );
+ BT_PROFILE( "integrateTransforms" );
+ int grainSize = 50; // num of iterations per task for TBB or OPENMP
+ if ( int bodyCount = m_nonStaticRigidBodies.size() )
+ {
+ UpdaterIntegrateTransforms update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
+ btPushThreadsAreRunning();
+ parallelFor( 0, bodyCount, grainSize, update );
+ btPopThreadsAreRunning();
+ }
+ }
+#endif // #if USE_PARALLEL_INTEGRATE_TRANSFORMS
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ MyDiscreteDynamicsWorld( btDispatcher* dispatcher,
+ btBroadphaseInterface* pairCache,
+ btConstraintSolver* constraintSolver,
+ btCollisionConfiguration* collisionConfiguration
+ ) :
+ btDiscreteDynamicsWorldMt( dispatcher, pairCache, constraintSolver, collisionConfiguration )
+ {
+ }
+
+};
+
+static bool gMultithreadedWorld = false;
+static bool gDisplayProfileInfo = false;
+static btScalar gSliderNumThreads = 1.0f; // should be int
+static btScalar gSliderSolverIterations = 10.0f; // should be int
+
+
+////////////////////////////////////
+CommonRigidBodyMTBase::CommonRigidBodyMTBase( struct GUIHelperInterface* helper )
+ :m_broadphase( 0 ),
+ m_dispatcher( 0 ),
+ m_solver( 0 ),
+ m_collisionConfiguration( 0 ),
+ m_dynamicsWorld( 0 ),
+ m_pickedBody( 0 ),
+ m_pickedConstraint( 0 ),
+ m_guiHelper( helper )
+{
+ m_multithreadedWorld = false;
+ m_multithreadCapable = false;
+ gTaskMgr.init();
+}
+
+CommonRigidBodyMTBase::~CommonRigidBodyMTBase()
+{
+ gTaskMgr.shutdown();
+}
+
+void boolPtrButtonCallback(int buttonId, bool buttonState, void* userPointer)
+{
+ if (bool* val = static_cast(userPointer))
+ {
+ *val = ! *val;
+ }
+}
+
+void apiSelectButtonCallback(int buttonId, bool buttonState, void* userPointer)
+{
+ gTaskMgr.setApi(static_cast(buttonId));
+ if (gTaskMgr.getApi()==TaskManager::apiNone)
+ {
+ gSliderNumThreads = 1.0f;
+ }
+ else
+ {
+ gSliderNumThreads = float(gTaskMgr.getNumThreads());
+ }
+}
+
+void setThreadCountCallback(float val, void* userPtr)
+{
+ if (gTaskMgr.getApi()==TaskManager::apiNone)
+ {
+ gSliderNumThreads = 1.0f;
+ }
+ else
+ {
+ gTaskMgr.setNumThreads( int( gSliderNumThreads ) );
+ }
+}
+
+void setSolverIterationCountCallback(float val, void* userPtr)
+{
+ if (btDiscreteDynamicsWorld* world = reinterpret_cast(userPtr))
+ {
+ world->getSolverInfo().m_numIterations = btMax(1, int(gSliderSolverIterations));
+ }
+}
+
+void CommonRigidBodyMTBase::createEmptyDynamicsWorld()
+{
+ gNumIslands = 0;
+#if BT_THREADSAFE && (BT_USE_OPENMP || BT_USE_PPL || BT_USE_TBB)
+ m_multithreadCapable = true;
+#endif
+ if ( gMultithreadedWorld )
+ {
+ m_dispatcher = NULL;
+ btDefaultCollisionConstructionInfo cci;
+ cci.m_defaultMaxPersistentManifoldPoolSize = 80000;
+ cci.m_defaultMaxCollisionAlgorithmPoolSize = 80000;
+ m_collisionConfiguration = new btDefaultCollisionConfiguration( cci );
+
+#if USE_PARALLEL_NARROWPHASE
+ m_dispatcher = new MyCollisionDispatcher( m_collisionConfiguration );
+#else
+ m_dispatcher = new btCollisionDispatcher( m_collisionConfiguration );
+#endif //USE_PARALLEL_NARROWPHASE
+
+ m_broadphase = new btDbvtBroadphase();
+
+#if USE_PARALLEL_ISLAND_SOLVER
+ m_solver = new MyConstraintSolverPool( TaskManager::getMaxNumThreads() );
+#else
+ m_solver = new btSequentialImpulseConstraintSolver();
+#endif //#if USE_PARALLEL_ISLAND_SOLVER
+ btDiscreteDynamicsWorld* world = new MyDiscreteDynamicsWorld( m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration );
+ m_dynamicsWorld = world;
+
+#if USE_PARALLEL_ISLAND_SOLVER
+ if ( btSimulationIslandManagerMt* islandMgr = dynamic_cast( world->getSimulationIslandManager() ) )
+ {
+ islandMgr->setIslandDispatchFunction( parallelIslandDispatch );
+ m_multithreadedWorld = true;
+ }
+#endif //#if USE_PARALLEL_ISLAND_SOLVER
+ }
+ else
+ {
+ // single threaded world
+ m_multithreadedWorld = false;
+
+ ///collision configuration contains default setup for memory, collision setup
+ m_collisionConfiguration = new btDefaultCollisionConfiguration();
+ //m_collisionConfiguration->setConvexConvexMultipointIterations();
+
+ ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
+ m_dispatcher = new btCollisionDispatcher( m_collisionConfiguration );
+
+ m_broadphase = new btDbvtBroadphase();
+
+ ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
+ btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
+ m_solver = sol;
+
+ m_dynamicsWorld = new btDiscreteDynamicsWorld( m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration );
+ }
+ m_dynamicsWorld->setInternalTickCallback( profileBeginCallback, NULL, true );
+ m_dynamicsWorld->setInternalTickCallback( profileEndCallback, NULL, false );
+ m_dynamicsWorld->setGravity( btVector3( 0, -10, 0 ) );
+ createDefaultParameters();
+}
+
+
+void CommonRigidBodyMTBase::createDefaultParameters()
+{
+ if (m_multithreadCapable)
+ {
+ // create a button to toggle multithreaded world
+ ButtonParams button( "Multithreaded world enable", 0, true );
+ button.m_userPointer = &gMultithreadedWorld;
+ button.m_callback = boolPtrButtonCallback;
+ m_guiHelper->getParameterInterface()->registerButtonParameter( button );
+ }
+ {
+ // create a button to toggle profile printing
+ ButtonParams button( "Display profile timings", 0, true );
+ button.m_userPointer = &gDisplayProfileInfo;
+ button.m_callback = boolPtrButtonCallback;
+ m_guiHelper->getParameterInterface()->registerButtonParameter( button );
+ }
+ {
+ SliderParams slider( "Solver iterations", &gSliderSolverIterations );
+ slider.m_minVal = 1.0f;
+ slider.m_maxVal = 30.0f;
+ slider.m_callback = setSolverIterationCountCallback;
+ slider.m_userPointer = m_dynamicsWorld;
+ slider.m_clampToIntegers = true;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ if (m_multithreadedWorld)
+ {
+ // create a button for each supported threading API
+ for (int iApi = 0; iApi < TaskManager::apiCount; ++iApi)
+ {
+ TaskManager::Api api = static_cast(iApi);
+ if (gTaskMgr.isSupported(api))
+ {
+ char str[1024];
+ sprintf(str, "API %s", gTaskMgr.getApiName(api));
+ ButtonParams button( str, iApi, false );
+ button.m_callback = apiSelectButtonCallback;
+ m_guiHelper->getParameterInterface()->registerButtonParameter( button );
+ }
+ }
+ {
+ // create a slider to set the number of threads to use
+ gSliderNumThreads = float(gTaskMgr.getNumThreads());
+ SliderParams slider("Thread count", &gSliderNumThreads);
+ slider.m_minVal = 1.0f;
+ slider.m_maxVal = float(gTaskMgr.getMaxNumThreads()*2);
+ slider.m_callback = setThreadCountCallback;
+ slider.m_clampToIntegers = true;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ }
+}
+
+void CommonRigidBodyMTBase::physicsDebugDraw(int debugFlags)
+{
+ if (m_dynamicsWorld && m_dynamicsWorld->getDebugDrawer())
+ {
+ m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugFlags);
+ m_dynamicsWorld->debugDrawWorld();
+ }
+ char msg[ 1024 ];
+ int xCoord = 400;
+ int yCoord = 30;
+ int yStep = 30;
+ if (m_multithreadCapable)
+ {
+ if ( m_multithreadedWorld != gMultithreadedWorld )
+ {
+ sprintf( msg, "restart example to begin in %s mode",
+ gMultithreadedWorld ? "multithreaded" : "single threaded"
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, 300, yCoord, 0.4f );
+ yCoord += yStep;
+ }
+ }
+ if (gDisplayProfileInfo)
+ {
+ if ( m_multithreadedWorld )
+ {
+ int numManifolds = m_dispatcher->getNumManifolds();
+ int numContacts = 0;
+ for ( int i = 0; i < numManifolds; ++i )
+ {
+ const btPersistentManifold* man = m_dispatcher->getManifoldByIndexInternal( i );
+ numContacts += man->getNumContacts();
+ }
+ const char* mtApi = TaskManager::getApiName( gTaskMgr.getApi() );
+ sprintf( msg, "islands=%d bodies=%d manifolds=%d contacts=%d [%s] threads=%d",
+ gNumIslands,
+ m_dynamicsWorld->getNumCollisionObjects(),
+ numManifolds,
+ numContacts,
+ mtApi,
+ gTaskMgr.getApi() == TaskManager::apiNone ? 1 : gTaskMgr.getNumThreads()
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, 100, yCoord, 0.4f );
+ yCoord += yStep;
+ }
+
+ sprintf( msg, "internalSimStep %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordInternalTimeStep )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+
+ if ( m_multithreadedWorld )
+ {
+ sprintf( msg,
+ "DispatchCollisionPairs %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordDispatchAllCollisionPairs )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+
+ sprintf( msg,
+ "SolveAllIslands %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordDispatchIslands )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+
+ sprintf( msg,
+ "PredictUnconstrainedMotion %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordPredictUnconstrainedMotion )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+
+ sprintf( msg,
+ "CreatePredictiveContacts %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordCreatePredictiveContacts )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+
+ sprintf( msg,
+ "IntegrateTransforms %5.3f ms",
+ gProfiler.getAverageTime( Profiler::kRecordIntegrateTransforms )*0.001f
+ );
+ m_guiHelper->getAppInterface()->drawText( msg, xCoord, yCoord, 0.4f );
+ yCoord += yStep;
+ }
+ }
+}
+
diff --git a/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h
new file mode 100644
index 000000000..7b19bdeaf
--- /dev/null
+++ b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h
@@ -0,0 +1,438 @@
+
+#ifndef COMMON_RIGID_BODY_MT_BASE_H
+#define COMMON_RIGID_BODY_MT_BASE_H
+
+
+#include "btBulletDynamicsCommon.h"
+#include "../CommonInterfaces/CommonExampleInterface.h"
+#include "../CommonInterfaces/CommonGUIHelperInterface.h"
+#include "../CommonInterfaces/CommonRenderInterface.h"
+#include "../CommonInterfaces/CommonCameraInterface.h"
+#include "../CommonInterfaces/CommonGraphicsAppInterface.h"
+#include "../CommonInterfaces/CommonWindowInterface.h"
+
+struct CommonRigidBodyMTBase : public CommonExampleInterface
+{
+ //keep the collision shapes, for deletion/cleanup
+ btAlignedObjectArray m_collisionShapes;
+ btBroadphaseInterface* m_broadphase;
+ btCollisionDispatcher* m_dispatcher;
+ btConstraintSolver* m_solver;
+ btDefaultCollisionConfiguration* m_collisionConfiguration;
+ btDiscreteDynamicsWorld* m_dynamicsWorld;
+ bool m_multithreadedWorld;
+ bool m_multithreadCapable;
+
+ //data for picking objects
+ class btRigidBody* m_pickedBody;
+ class btTypedConstraint* m_pickedConstraint;
+ int m_savedState;
+ btVector3 m_oldPickingPos;
+ btVector3 m_hitPos;
+ btScalar m_oldPickingDist;
+ struct GUIHelperInterface* m_guiHelper;
+
+ CommonRigidBodyMTBase(struct GUIHelperInterface* helper);
+ virtual ~CommonRigidBodyMTBase();
+
+
+ btDiscreteDynamicsWorld* getDynamicsWorld()
+ {
+ return m_dynamicsWorld;
+ }
+
+ virtual void createDefaultParameters();
+ virtual void createEmptyDynamicsWorld();
+
+ virtual void stepSimulation(float deltaTime)
+ {
+ if (m_dynamicsWorld)
+ {
+ m_dynamicsWorld->stepSimulation(deltaTime);
+ }
+ }
+
+ virtual void physicsDebugDraw(int debugFlags);
+
+ virtual void exitPhysics()
+ {
+ removePickingConstraint();
+ //cleanup in the reverse order of creation/initialization
+
+ //remove the rigidbodies from the dynamics world and delete them
+
+ if (m_dynamicsWorld)
+ {
+
+ int i;
+ for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--)
+ {
+ m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
+ }
+ for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
+ {
+ btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
+ btRigidBody* body = btRigidBody::upcast(obj);
+ if (body && body->getMotionState())
+ {
+ delete body->getMotionState();
+ }
+ m_dynamicsWorld->removeCollisionObject(obj);
+ delete obj;
+ }
+ }
+ //delete collision shapes
+ for (int j = 0; jgetDebugDrawer())
+ {
+ m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugDrawFlags);
+ }
+ m_dynamicsWorld->debugDrawWorld();
+ }
+
+ }
+
+ virtual bool keyboardCallback(int key, int state)
+ {
+ if ((key==B3G_F3) && state && m_dynamicsWorld)
+ {
+ btDefaultSerializer* serializer = new btDefaultSerializer();
+ m_dynamicsWorld->serialize(serializer);
+
+ FILE* file = fopen("testFile.bullet","wb");
+ fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file);
+ fclose(file);
+ //b3Printf("btDefaultSerializer wrote testFile.bullet");
+ delete serializer;
+ return true;
+
+ }
+ return false;//don't handle this key
+ }
+
+
+ btVector3 getRayTo(int x,int y)
+ {
+ CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
+
+ if (!renderer)
+ {
+ btAssert(0);
+ return btVector3(0,0,0);
+ }
+
+ float top = 1.f;
+ float bottom = -1.f;
+ float nearPlane = 1.f;
+ float tanFov = (top-bottom)*0.5f / nearPlane;
+ float fov = btScalar(2.0) * btAtan(tanFov);
+
+ btVector3 camPos,camTarget;
+
+ renderer->getActiveCamera()->getCameraPosition(camPos);
+ renderer->getActiveCamera()->getCameraTargetPosition(camTarget);
+
+ btVector3 rayFrom = camPos;
+ btVector3 rayForward = (camTarget-camPos);
+ rayForward.normalize();
+ float farPlane = 10000.f;
+ rayForward*= farPlane;
+
+ btVector3 rightOffset;
+ btVector3 cameraUp=btVector3(0,0,0);
+ cameraUp[m_guiHelper->getAppInterface()->getUpAxis()]=1;
+
+ btVector3 vertical = cameraUp;
+
+ btVector3 hor;
+ hor = rayForward.cross(vertical);
+ hor.safeNormalize();
+ vertical = hor.cross(rayForward);
+ vertical.safeNormalize();
+
+ float tanfov = tanf(0.5f*fov);
+
+
+ hor *= 2.f * farPlane * tanfov;
+ vertical *= 2.f * farPlane * tanfov;
+
+ btScalar aspect;
+ float width = float(renderer->getScreenWidth());
+ float height = float (renderer->getScreenHeight());
+
+ aspect = width / height;
+
+ hor*=aspect;
+
+
+ btVector3 rayToCenter = rayFrom + rayForward;
+ btVector3 dHor = hor * 1.f/width;
+ btVector3 dVert = vertical * 1.f/height;
+
+
+ btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
+ rayTo += btScalar(x) * dHor;
+ rayTo -= btScalar(y) * dVert;
+ return rayTo;
+ }
+
+ virtual bool mouseMoveCallback(float x,float y)
+ {
+ CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
+
+ if (!renderer)
+ {
+ btAssert(0);
+ return false;
+ }
+
+ btVector3 rayTo = getRayTo(int(x), int(y));
+ btVector3 rayFrom;
+ renderer->getActiveCamera()->getCameraPosition(rayFrom);
+ movePickedBody(rayFrom,rayTo);
+
+ return false;
+ }
+
+ virtual bool mouseButtonCallback(int button, int state, float x, float y)
+ {
+ CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
+
+ if (!renderer)
+ {
+ btAssert(0);
+ return false;
+ }
+
+ CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
+
+#if 0
+ if (window->isModifierKeyPressed(B3G_ALT))
+ {
+ printf("ALT pressed\n");
+ } else
+ {
+ printf("NO ALT pressed\n");
+ }
+
+ if (window->isModifierKeyPressed(B3G_SHIFT))
+ {
+ printf("SHIFT pressed\n");
+ } else
+ {
+ printf("NO SHIFT pressed\n");
+ }
+
+ if (window->isModifierKeyPressed(B3G_CONTROL))
+ {
+ printf("CONTROL pressed\n");
+ } else
+ {
+ printf("NO CONTROL pressed\n");
+ }
+#endif
+
+
+ if (state==1)
+ {
+ if(button==0 && (!window->isModifierKeyPressed(B3G_ALT) && !window->isModifierKeyPressed(B3G_CONTROL) ))
+ {
+ btVector3 camPos;
+ renderer->getActiveCamera()->getCameraPosition(camPos);
+
+ btVector3 rayFrom = camPos;
+ btVector3 rayTo = getRayTo(int(x),int(y));
+
+ pickBody(rayFrom, rayTo);
+
+
+ }
+ } else
+ {
+ if (button==0)
+ {
+ removePickingConstraint();
+ //remove p2p
+ }
+ }
+
+ //printf("button=%d, state=%d\n",button,state);
+ return false;
+ }
+
+
+ virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+ {
+ if (m_dynamicsWorld==0)
+ return false;
+
+ btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);
+
+ m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
+ if (rayCallback.hasHit())
+ {
+
+ btVector3 pickPos = rayCallback.m_hitPointWorld;
+ btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
+ if (body)
+ {
+ //other exclusions?
+ if (!(body->isStaticObject() || body->isKinematicObject()))
+ {
+ m_pickedBody = body;
+ m_savedState = m_pickedBody->getActivationState();
+ m_pickedBody->setActivationState(DISABLE_DEACTIVATION);
+ //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ());
+ btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
+ btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot);
+ m_dynamicsWorld->addConstraint(p2p, true);
+ m_pickedConstraint = p2p;
+ btScalar mousePickClamping = 30.f;
+ p2p->m_setting.m_impulseClamp = mousePickClamping;
+ //very weak constraint for picking
+ p2p->m_setting.m_tau = 0.001f;
+ }
+ }
+
+
+ // pickObject(pickPos, rayCallback.m_collisionObject);
+ m_oldPickingPos = rayToWorld;
+ m_hitPos = pickPos;
+ m_oldPickingDist = (pickPos - rayFromWorld).length();
+ // printf("hit !\n");
+ //add p2p
+ }
+ return false;
+ }
+ virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+ {
+ if (m_pickedBody && m_pickedConstraint)
+ {
+ btPoint2PointConstraint* pickCon = static_cast(m_pickedConstraint);
+ if (pickCon)
+ {
+ //keep it at the same picking distance
+
+ btVector3 newPivotB;
+
+ btVector3 dir = rayToWorld - rayFromWorld;
+ dir.normalize();
+ dir *= m_oldPickingDist;
+
+ newPivotB = rayFromWorld + dir;
+ pickCon->setPivotB(newPivotB);
+ return true;
+ }
+ }
+ return false;
+ }
+ virtual void removePickingConstraint()
+ {
+ if (m_pickedConstraint)
+ {
+ m_pickedBody->forceActivationState(m_savedState);
+ m_pickedBody->activate();
+ m_dynamicsWorld->removeConstraint(m_pickedConstraint);
+ delete m_pickedConstraint;
+ m_pickedConstraint = 0;
+ m_pickedBody = 0;
+ }
+ }
+
+
+
+ btBoxShape* createBoxShape(const btVector3& halfExtents)
+ {
+ btBoxShape* box = new btBoxShape(halfExtents);
+ return box;
+ }
+
+ btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1))
+ {
+ btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
+
+ //rigidbody is dynamic if and only if mass is non zero, otherwise static
+ bool isDynamic = (mass != 0.f);
+
+ btVector3 localInertia(0, 0, 0);
+ if (isDynamic)
+ shape->calculateLocalInertia(mass, localInertia);
+
+ //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
+
+#define USE_MOTIONSTATE 1
+#ifdef USE_MOTIONSTATE
+ btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
+
+ btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia);
+
+ btRigidBody* body = new btRigidBody(cInfo);
+ //body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
+
+#else
+ btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia);
+ body->setWorldTransform(startTransform);
+#endif//
+
+ body->setUserIndex(-1);
+ m_dynamicsWorld->addRigidBody(body);
+ return body;
+ }
+
+ btRigidBody* createKinematicBody(const btTransform& startTransform, btCollisionShape* shape)
+ {
+ btAssert( ( !shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE ) );
+
+ btRigidBody* body = new btRigidBody( 0.0f, NULL, shape );
+ body->setWorldTransform( startTransform );
+ body->setCollisionFlags( body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT );
+ body->setUserIndex( -1 );
+ m_dynamicsWorld->addRigidBody( body );
+ return body;
+ }
+
+
+ virtual void renderScene()
+ {
+ {
+
+ m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
+ }
+
+ {
+
+ m_guiHelper->render(m_dynamicsWorld);
+ }
+ }
+};
+
+#endif //#define COMMON_RIGID_BODY_MT_BASE_H
+
+
diff --git a/examples/MultiThreadedDemo/MultiThreadedDemo.cpp b/examples/MultiThreadedDemo/MultiThreadedDemo.cpp
new file mode 100644
index 000000000..3dff09ae8
--- /dev/null
+++ b/examples/MultiThreadedDemo/MultiThreadedDemo.cpp
@@ -0,0 +1,281 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "../CommonInterfaces/CommonParameterInterface.h"
+#include //printf debugging
+#include
+
+class btCollisionShape;
+
+#include "CommonRigidBodyMTBase.h"
+#include "MultiThreadedDemo.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btBulletCollisionCommon.h"
+
+
+#define BT_OVERRIDE
+
+static btScalar gSliderStackRows = 8.0f;
+static btScalar gSliderStackColumns = 6.0f;
+static btScalar gSliderStackHeight = 15.0f;
+static btScalar gSliderGroundHorizontalAmplitude = 0.0f;
+static btScalar gSliderGroundVerticalAmplitude = 0.0f;
+
+
+/// MultiThreadedDemo shows how to setup and use multithreading
+class MultiThreadedDemo : public CommonRigidBodyMTBase
+{
+ static const int kUpAxis = 1;
+
+ btRigidBody* localCreateRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* colSape);
+
+ btVector3 m_cameraTargetPos;
+ float m_cameraPitch;
+ float m_cameraYaw;
+ float m_cameraDist;
+ btRigidBody* m_groundBody;
+ btTransform m_groundStartXf;
+ float m_groundMovePhase;
+
+ void createStack( const btVector3& pos, btCollisionShape* boxShape, const btVector3& halfBoxSize, int size );
+ void createSceneObjects();
+ void destroySceneObjects();
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ MultiThreadedDemo( struct GUIHelperInterface* helper );
+
+ virtual ~MultiThreadedDemo() {}
+
+ virtual void stepSimulation( float deltaTime ) BT_OVERRIDE
+ {
+ if ( m_dynamicsWorld )
+ {
+ if (m_groundBody)
+ {
+ // update ground
+ const float cyclesPerSecond = 1.0f;
+ m_groundMovePhase += cyclesPerSecond * deltaTime;
+ m_groundMovePhase -= floor( m_groundMovePhase ); // keep phase between 0 and 1
+ btTransform xf = m_groundStartXf;
+ float gndHOffset = btSin(m_groundMovePhase * SIMD_2_PI) * gSliderGroundHorizontalAmplitude;
+ float gndHVel = btCos(m_groundMovePhase * SIMD_2_PI) * gSliderGroundHorizontalAmplitude * cyclesPerSecond * SIMD_2_PI; // d(gndHOffset)/dt
+ float gndVOffset = btSin(m_groundMovePhase * SIMD_2_PI) * gSliderGroundVerticalAmplitude;
+ float gndVVel = btCos(m_groundMovePhase * SIMD_2_PI) * gSliderGroundVerticalAmplitude * cyclesPerSecond * SIMD_2_PI; // d(gndVOffset)/dt
+ btVector3 offset(0,0,0);
+ btVector3 vel(0,0,0);
+ int horizAxis = 2;
+ offset[horizAxis] = gndHOffset;
+ vel[horizAxis] = gndHVel;
+ offset[kUpAxis] = gndVOffset;
+ vel[kUpAxis] = gndVVel;
+ xf.setOrigin(xf.getOrigin() + offset);
+ m_groundBody->setWorldTransform( xf );
+ m_groundBody->setLinearVelocity( vel );
+ }
+ // always step by 1/60 for benchmarking
+ m_dynamicsWorld->stepSimulation( 1.0f / 60.0f, 0 );
+ }
+ }
+
+ virtual void initPhysics() BT_OVERRIDE;
+ virtual void resetCamera() BT_OVERRIDE
+ {
+ m_guiHelper->resetCamera( m_cameraDist,
+ m_cameraPitch,
+ m_cameraYaw,
+ m_cameraTargetPos.x(),
+ m_cameraTargetPos.y(),
+ m_cameraTargetPos.z()
+ );
+ }
+
+};
+
+
+MultiThreadedDemo::MultiThreadedDemo(struct GUIHelperInterface* helper)
+ : CommonRigidBodyMTBase( helper )
+{
+ m_groundBody = NULL;
+ m_groundMovePhase = 0.0f;
+ m_cameraTargetPos = btVector3( 0.0f, 0.0f, 0.0f );
+ m_cameraPitch = 90.0f;
+ m_cameraYaw = 30.0f;
+ m_cameraDist = 48.0f;
+ helper->setUpAxis( kUpAxis );
+}
+
+
+void MultiThreadedDemo::initPhysics()
+{
+ createEmptyDynamicsWorld();
+
+ m_dynamicsWorld->setGravity( btVector3( 0, -10, 0 ) );
+
+ {
+ SliderParams slider( "Stack height", &gSliderStackHeight );
+ slider.m_minVal = 1.0f;
+ slider.m_maxVal = 30.0f;
+ slider.m_clampToIntegers = true;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ {
+ SliderParams slider( "Stack rows", &gSliderStackRows );
+ slider.m_minVal = 1.0f;
+ slider.m_maxVal = 20.0f;
+ slider.m_clampToIntegers = true;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ {
+ SliderParams slider( "Stack columns", &gSliderStackColumns );
+ slider.m_minVal = 1.0f;
+ slider.m_maxVal = 20.0f;
+ slider.m_clampToIntegers = true;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ {
+ // horizontal ground shake
+ SliderParams slider( "Ground horiz amp", &gSliderGroundHorizontalAmplitude );
+ slider.m_minVal = 0.0f;
+ slider.m_maxVal = 1.0f;
+ slider.m_clampToNotches = false;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+ {
+ // vertical ground shake
+ SliderParams slider( "Ground vert amp", &gSliderGroundVerticalAmplitude );
+ slider.m_minVal = 0.0f;
+ slider.m_maxVal = 1.0f;
+ slider.m_clampToNotches = false;
+ m_guiHelper->getParameterInterface()->registerSliderFloatParameter( slider );
+ }
+
+ createSceneObjects();
+
+ m_guiHelper->createPhysicsDebugDrawer( m_dynamicsWorld );
+}
+
+
+
+btRigidBody* MultiThreadedDemo::localCreateRigidBody(btScalar mass, const btTransform& startTransform, btCollisionShape* shape)
+{
+ btRigidBody* body = createRigidBody(mass, startTransform, shape);
+ if ( mass > 0.0f )
+ {
+ // prevent bodies from sleeping to make profiling/benchmarking easier
+ body->forceActivationState( DISABLE_DEACTIVATION );
+ }
+ return body;
+}
+
+
+void MultiThreadedDemo::createStack( const btVector3& center, btCollisionShape* boxShape, const btVector3& halfBoxSize, int size )
+{
+ btTransform trans;
+ trans.setIdentity();
+ float halfBoxHeight = halfBoxSize.y();
+ float halfBoxWidth = halfBoxSize.x();
+
+ for ( int i = 0; isetFriction(1.0f);
+ }
+ }
+}
+
+
+void MultiThreadedDemo::createSceneObjects()
+{
+ {
+ // create ground box
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin( btVector3( 0.f, -3.f, 0.f ) );
+ m_groundStartXf = tr;
+
+ //either use heightfield or triangle mesh
+
+ btVector3 groundExtents( 400, 400, 400 );
+ groundExtents[ kUpAxis ] = 3;
+ btCollisionShape* groundShape = new btBoxShape( groundExtents );
+ m_collisionShapes.push_back( groundShape );
+
+ //create ground object
+ m_groundBody = createKinematicBody( m_groundStartXf, groundShape );
+ m_groundBody->forceActivationState( DISABLE_DEACTIVATION );
+ m_groundBody->setFriction(1.0f);
+ }
+
+ {
+ // create walls of cubes
+ const btVector3 halfExtents = btVector3( 0.5f, 0.25f, 0.5f );
+ int numStackRows = btMax(1, int(gSliderStackRows));
+ int numStackCols = btMax(1, int(gSliderStackColumns));
+ int stackHeight = 15;
+ float stackZSpacing = 3.0f;
+ float stackXSpacing = 20.0f;
+
+ btBoxShape* boxShape = new btBoxShape( halfExtents );
+ m_collisionShapes.push_back( boxShape );
+
+ for ( int iX = 0; iX < numStackCols; ++iX )
+ {
+ for ( int iZ = 0; iZ < numStackRows; ++iZ )
+ {
+ btVector3 center = btVector3( iX * stackXSpacing, 0.0f, ( iZ - numStackRows / 2 ) * stackZSpacing );
+ createStack( center, boxShape, halfExtents, stackHeight );
+ }
+ }
+ }
+#if 0
+ if ( false )
+ {
+ // destroyer ball
+ btTransform sphereTrans;
+ sphereTrans.setIdentity();
+ sphereTrans.setOrigin( btVector3( 0, 2, 40 ) );
+ btSphereShape* ball = new btSphereShape( 2.f );
+ m_collisionShapes.push_back( ball );
+ btRigidBody* ballBody = localCreateRigidBody( 10000.f, sphereTrans, ball );
+ ballBody->setLinearVelocity( btVector3( 0, 0, -10 ) );
+ }
+#endif
+ m_guiHelper->autogenerateGraphicsObjects( m_dynamicsWorld );
+
+}
+
+
+CommonExampleInterface* MultiThreadedDemoCreateFunc( struct CommonExampleOptions& options )
+{
+ return new MultiThreadedDemo(options.m_guiHelper);
+}
+
diff --git a/examples/MultiThreadedDemo/MultiThreadedDemo.h b/examples/MultiThreadedDemo/MultiThreadedDemo.h
new file mode 100644
index 000000000..0075e81e7
--- /dev/null
+++ b/examples/MultiThreadedDemo/MultiThreadedDemo.h
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef MULTITHREADED_DEMO_H
+#define MULTITHREADED_DEMO_H
+
+class CommonExampleInterface* MultiThreadedDemoCreateFunc(struct CommonExampleOptions& options);
+
+#endif // MULTITHREADED_DEMO_H
+
+
diff --git a/examples/MultiThreadedDemo/ParallelFor.h b/examples/MultiThreadedDemo/ParallelFor.h
new file mode 100644
index 000000000..77f6dfe39
--- /dev/null
+++ b/examples/MultiThreadedDemo/ParallelFor.h
@@ -0,0 +1,336 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include //printf debugging
+#include
+
+
+// choose threading providers:
+#if BT_USE_TBB
+#define USE_TBB 1 // use Intel Threading Building Blocks for thread management
+#endif
+
+#if BT_USE_PPL
+#define USE_PPL 1 // use Microsoft Parallel Patterns Library (installed with Visual Studio 2010 and later)
+#endif // BT_USE_PPL
+
+#if BT_USE_OPENMP
+#define USE_OPENMP 1 // use OpenMP (also need to change compiler options for OpenMP support)
+#endif
+
+
+#if USE_OPENMP
+
+#include
+
+#endif // #if USE_OPENMP
+
+
+#if USE_PPL
+
+#include // if you get a compile error here, check whether your version of Visual Studio includes PPL
+// Visual Studio 2010 and later should come with it
+#include // for GetProcessorCount()
+#endif // #if USE_PPL
+
+
+#if USE_TBB
+
+#define __TBB_NO_IMPLICIT_LINKAGE 1
+#include
+#include
+#include
+#include
+
+#endif // #if USE_TBB
+
+
+
+class TaskManager
+{
+public:
+ enum Api
+ {
+ apiNone,
+ apiOpenMP,
+ apiTbb,
+ apiPpl,
+ apiCount
+ };
+ static const char* getApiName( Api api )
+ {
+ switch ( api )
+ {
+ case apiNone: return "None";
+ case apiOpenMP: return "OpenMP";
+ case apiTbb: return "Intel TBB";
+ case apiPpl: return "MS PPL";
+ default: return "unknown";
+ }
+ }
+
+ TaskManager()
+ {
+ m_api = apiNone;
+ m_numThreads = 0;
+#if USE_TBB
+ m_tbbSchedulerInit = NULL;
+#endif // #if USE_TBB
+ }
+
+ Api getApi() const
+ {
+ return m_api;
+ }
+
+ bool isSupported( Api api ) const
+ {
+#if USE_OPENMP
+ if ( api == apiOpenMP )
+ {
+ return true;
+ }
+#endif
+#if USE_TBB
+ if ( api == apiTbb )
+ {
+ return true;
+ }
+#endif
+#if USE_PPL
+ if ( api == apiPpl )
+ {
+ return true;
+ }
+#endif
+ // apiNone is always "supported"
+ return api == apiNone;
+ }
+
+ void setApi( Api api )
+ {
+ if (isSupported(api))
+ {
+ m_api = api;
+ }
+ else
+ {
+ // no compile time support for selected API, fallback to "none"
+ m_api = apiNone;
+ }
+ }
+
+ static int getMaxNumThreads()
+ {
+#if USE_OPENMP
+ return omp_get_max_threads();
+#elif USE_PPL
+ return concurrency::GetProcessorCount();
+#elif USE_TBB
+ return tbb::task_scheduler_init::default_num_threads();
+#endif
+ return 1;
+ }
+
+ int getNumThreads() const
+ {
+ return m_numThreads;
+ }
+
+ int setNumThreads( int numThreads )
+ {
+ m_numThreads = ( std::max )( 1, numThreads );
+
+#if USE_OPENMP
+ omp_set_num_threads( m_numThreads );
+#endif
+
+#if USE_PPL
+ {
+ using namespace concurrency;
+ if ( CurrentScheduler::Id() != -1 )
+ {
+ CurrentScheduler::Detach();
+ }
+ SchedulerPolicy policy;
+ policy.SetConcurrencyLimits( m_numThreads, m_numThreads );
+ CurrentScheduler::Create( policy );
+ }
+#endif
+
+#if USE_TBB
+ if ( m_tbbSchedulerInit )
+ {
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+ m_tbbSchedulerInit = new tbb::task_scheduler_init( m_numThreads );
+#endif
+ return m_numThreads;
+ }
+
+ void init()
+ {
+ if (m_numThreads == 0)
+ {
+#if USE_PPL
+ setApi( apiPpl );
+#endif
+#if USE_TBB
+ setApi( apiTbb );
+#endif
+#if USE_OPENMP
+ setApi( apiOpenMP );
+#endif
+ setNumThreads(getMaxNumThreads());
+ }
+ else
+ {
+ setNumThreads(m_numThreads);
+ }
+ }
+
+ void shutdown()
+ {
+#if USE_TBB
+ if ( m_tbbSchedulerInit )
+ {
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+#endif
+ }
+
+private:
+ Api m_api;
+ int m_numThreads;
+#if USE_TBB
+ tbb::task_scheduler_init* m_tbbSchedulerInit;
+#endif // #if USE_TBB
+};
+
+extern TaskManager gTaskMgr;
+
+
+static void initTaskScheduler()
+{
+ gTaskMgr.init();
+}
+
+static void cleanupTaskScheduler()
+{
+ gTaskMgr.shutdown();
+}
+
+
+#if USE_TBB
+///
+/// TbbBodyAdapter -- Converts a body object that implements the
+/// "forLoop(int iBegin, int iEnd) const" function
+/// into a TBB compatible object that takes a tbb::blocked_range type.
+///
+template
+struct TbbBodyAdapter
+{
+ const TBody* mBody;
+
+ void operator()( const tbb::blocked_range& range ) const
+ {
+ mBody->forLoop( range.begin(), range.end() );
+ }
+};
+#endif // #if USE_TBB
+
+#if USE_PPL
+///
+/// PplBodyAdapter -- Converts a body object that implements the
+/// "forLoop(int iBegin, int iEnd) const" function
+/// into a PPL compatible object that implements "void operator()( int ) const"
+///
+template
+struct PplBodyAdapter
+{
+ const TBody* mBody;
+ int mGrainSize;
+ int mIndexEnd;
+
+ void operator()( int i ) const
+ {
+ mBody->forLoop( i, (std::min)(i + mGrainSize, mIndexEnd) );
+ }
+};
+#endif // #if USE_PPL
+
+
+///
+/// parallelFor -- interface for submitting work expressed as a for loop to the worker threads
+///
+template
+void parallelFor( int iBegin, int iEnd, int grainSize, const TBody& body )
+{
+#if USE_OPENMP
+ if ( gTaskMgr.getApi() == TaskManager::apiOpenMP )
+ {
+#pragma omp parallel for schedule(static, 1)
+ for ( int i = iBegin; i < iEnd; i += grainSize )
+ {
+ body.forLoop( i, (std::min)( i + grainSize, iEnd ) );
+ }
+ return;
+ }
+#endif // #if USE_OPENMP
+
+#if USE_PPL
+ if ( gTaskMgr.getApi() == TaskManager::apiPpl )
+ {
+ // PPL dispatch
+ PplBodyAdapter pplBody;
+ pplBody.mBody = &body;
+ pplBody.mGrainSize = grainSize;
+ pplBody.mIndexEnd = iEnd;
+ // note: MSVC 2010 doesn't support partitioner args, so avoid them
+ concurrency::parallel_for( iBegin,
+ iEnd,
+ grainSize,
+ pplBody
+ );
+ return;
+ }
+#endif //#if USE_PPL
+
+#if USE_TBB
+ if ( gTaskMgr.getApi() == TaskManager::apiTbb )
+ {
+ // TBB dispatch
+ TbbBodyAdapter tbbBody;
+ tbbBody.mBody = &body;
+ tbb::parallel_for( tbb::blocked_range( iBegin, iEnd, grainSize ),
+ tbbBody,
+ tbb::simple_partitioner()
+ );
+ return;
+ }
+#endif // #if USE_TBB
+
+ {
+ // run on main thread
+ body.forLoop( iBegin, iEnd );
+ }
+
+}
+
+
+
+
diff --git a/examples/MultiThreading/MultiThreadingExample.cpp b/examples/MultiThreading/MultiThreadingExample.cpp
index 1969912b9..33eb0e751 100644
--- a/examples/MultiThreading/MultiThreadingExample.cpp
+++ b/examples/MultiThreading/MultiThreadingExample.cpp
@@ -11,6 +11,7 @@
#include "stb_image/stb_image.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3Matrix3x3.h"
+#include "../Utils/b3Clock.h"
#include "../CommonInterfaces/CommonParameterInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
@@ -134,6 +135,8 @@ void SampleThreadFunc(void* userPtr,void* lsMemory)
job->executeJob(localStorage->threadId);
}
+ b3Clock::usleep(250);
+
args->m_cs->lock();
int exitMagicNumber = args->m_cs->getSharedParam(1);
requestExit = (exitMagicNumber==MAGIC_RESET_NUMBER);
diff --git a/examples/OpenCL/rigidbody/GpuRigidBodyDemo.cpp b/examples/OpenCL/rigidbody/GpuRigidBodyDemo.cpp
index d2ee9794a..c7b821dbf 100644
--- a/examples/OpenCL/rigidbody/GpuRigidBodyDemo.cpp
+++ b/examples/OpenCL/rigidbody/GpuRigidBodyDemo.cpp
@@ -80,7 +80,18 @@ m_window(0)
m_window = helper->getAppInterface()->m_window;
m_data = new GpuRigidBodyDemoInternalData;
+ m_data->m_guiHelper = helper;
}
+
+void GpuRigidBodyDemo::resetCamera()
+{
+ float dist = 114;
+ float pitch = 52;
+ float yaw = 35;
+ float targetPos[3]={0,0,0};
+ m_data->m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
+}
+
GpuRigidBodyDemo::~GpuRigidBodyDemo()
{
diff --git a/examples/OpenCL/rigidbody/GpuRigidBodyDemo.h b/examples/OpenCL/rigidbody/GpuRigidBodyDemo.h
index 7e58b9e7d..a62fdab9e 100644
--- a/examples/OpenCL/rigidbody/GpuRigidBodyDemo.h
+++ b/examples/OpenCL/rigidbody/GpuRigidBodyDemo.h
@@ -31,7 +31,8 @@ public:
virtual void renderScene();
-
+ void resetCamera();
+
virtual void stepSimulation(float deltaTime);
//for picking
diff --git a/examples/OpenCL/rigidbody/GpuRigidBodyDemoInternalData.h b/examples/OpenCL/rigidbody/GpuRigidBodyDemoInternalData.h
index 9147a5080..8c7b5f5bb 100644
--- a/examples/OpenCL/rigidbody/GpuRigidBodyDemoInternalData.h
+++ b/examples/OpenCL/rigidbody/GpuRigidBodyDemoInternalData.h
@@ -32,6 +32,7 @@ struct GpuRigidBodyDemoInternalData
int m_pickGraphicsShapeIndex;
int m_pickGraphicsShapeInstance;
b3Config m_config;
+ GUIHelperInterface* m_guiHelper;
GpuRigidBodyDemoInternalData()
:m_instancePosOrnColor(0),
@@ -45,7 +46,8 @@ struct GpuRigidBodyDemoInternalData
m_pickGraphicsShapeInstance(-1),
m_pickBody(-1),
m_altPressed(0),
- m_controlPressed(0)
+ m_controlPressed(0),
+ m_guiHelper(0)
{
}
diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp
index 718a9fc60..c6f620bab 100644
--- a/examples/OpenGLWindow/GLInstancingRenderer.cpp
+++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp
@@ -17,9 +17,9 @@ subject to the following restrictions:
///todo: make this configurable in the gui
bool useShadowMap = true;// true;//false;//true;
-int shadowMapWidth= 2048;
-int shadowMapHeight= 2048;
-float shadowMapWorldSize=5;
+int shadowMapWidth= 4096;
+int shadowMapHeight= 4096;
+float shadowMapWorldSize=10;
#define MAX_POINTS_IN_BATCH 1024
#define MAX_LINES_IN_BATCH 1024
@@ -1539,7 +1539,7 @@ void GLInstancingRenderer::renderSceneInternal(int renderMode)
b3Assert(glGetError() ==GL_NO_ERROR);
} else
{
- //glDisable(GL_CULL_FACE);
+ glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
diff --git a/examples/OpenGLWindow/SimpleOpenGL2App.cpp b/examples/OpenGLWindow/SimpleOpenGL2App.cpp
index 62f8aba16..710b9fdab 100644
--- a/examples/OpenGLWindow/SimpleOpenGL2App.cpp
+++ b/examples/OpenGLWindow/SimpleOpenGL2App.cpp
@@ -70,6 +70,11 @@ struct SimpleOpenGL2AppInternalData
{
GLuint m_fontTextureId;
GLuint m_largeFontTextureId;
+ int m_upAxis;
+ SimpleOpenGL2AppInternalData()
+ :m_upAxis(1)
+ {
+ }
};
static GLuint BindFont2(const CTexFont *_Font)
@@ -268,10 +273,11 @@ void SimpleOpenGL2App::drawGrid(DrawGridData data)
}
void SimpleOpenGL2App::setUpAxis(int axis)
{
+ this->m_data->m_upAxis = axis;
}
int SimpleOpenGL2App::getUpAxis() const
{
- return 1;
+ return this->m_data->m_upAxis;
}
void SimpleOpenGL2App::swapBuffer()
@@ -280,7 +286,7 @@ void SimpleOpenGL2App::swapBuffer()
m_window->startRendering();
}
-void SimpleOpenGL2App::drawText( const char* txt, int posX, int posY)
+void SimpleOpenGL2App::drawText( const char* txt, int posX, int posY, float size)
{
}
diff --git a/examples/OpenGLWindow/SimpleOpenGL2App.h b/examples/OpenGLWindow/SimpleOpenGL2App.h
index 960dc1d07..3b8a54a5b 100644
--- a/examples/OpenGLWindow/SimpleOpenGL2App.h
+++ b/examples/OpenGLWindow/SimpleOpenGL2App.h
@@ -17,7 +17,7 @@ public:
virtual int getUpAxis() const;
virtual void swapBuffer();
- virtual void drawText( const char* txt, int posX, int posY);
+ virtual void drawText( const char* txt, int posX, int posY, float size);
virtual void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA){};
virtual void setBackgroundColor(float red, float green, float blue);
virtual int registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ, int textureIndex = -1, float textureScaling = 1)
diff --git a/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp b/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp
index 050ec447e..d69b63d54 100644
--- a/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp
+++ b/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp
@@ -33,6 +33,7 @@ void SimpleOpenGL2Renderer::updateCamera(int upAxis)
float projection[16];
float view[16];
m_camera.setAspectRatio((float)m_width/(float)m_height);
+ m_camera.setCameraUpAxis(upAxis);
m_camera.update();
m_camera.getCameraProjectionMatrix(projection);
m_camera.getCameraViewMatrix(view);
diff --git a/examples/OpenGLWindow/SimpleOpenGL3App.cpp b/examples/OpenGLWindow/SimpleOpenGL3App.cpp
index 6abcd2185..aea665019 100644
--- a/examples/OpenGLWindow/SimpleOpenGL3App.cpp
+++ b/examples/OpenGLWindow/SimpleOpenGL3App.cpp
@@ -352,7 +352,7 @@ void SimpleOpenGL3App::drawText3D( const char* txt, float worldPosX, float world
}
-void SimpleOpenGL3App::drawText( const char* txt, int posXi, int posYi)
+void SimpleOpenGL3App::drawText( const char* txt, int posXi, int posYi, float size)
{
float posX = (float)posXi;
@@ -374,7 +374,7 @@ void SimpleOpenGL3App::drawText( const char* txt, int posXi, int posYi)
{
bool measureOnly = false;
- float fontSize= 64;//512;//128;
+ float fontSize= 64*size;//512;//128;
sth_draw_text(m_data->m_fontStash,
m_data->m_droidRegular,fontSize,posX,posY,
txt,&dx, this->m_instancingRenderer->getScreenWidth(),
diff --git a/examples/OpenGLWindow/SimpleOpenGL3App.h b/examples/OpenGLWindow/SimpleOpenGL3App.h
index 8a3f477f6..6902dacf8 100644
--- a/examples/OpenGLWindow/SimpleOpenGL3App.h
+++ b/examples/OpenGLWindow/SimpleOpenGL3App.h
@@ -31,7 +31,7 @@ struct SimpleOpenGL3App : public CommonGraphicsApp
virtual int getUpAxis() const;
virtual void swapBuffer();
- virtual void drawText( const char* txt, int posX, int posY);
+ virtual void drawText( const char* txt, int posX, int posY, float size=1.0f);
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size);
virtual void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA);
struct sth_stash* getFontStash();
diff --git a/examples/Raycast/RaytestDemo.cpp b/examples/Raycast/RaytestDemo.cpp
index fa07a9942..5bf458d7e 100644
--- a/examples/Raycast/RaytestDemo.cpp
+++ b/examples/Raycast/RaytestDemo.cpp
@@ -200,7 +200,6 @@ void RaytestDemo::initPhysics()
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
- body->setRollingFriction(1);
body->setFriction(1);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
@@ -269,6 +268,7 @@ void RaytestDemo::initPhysics()
rbInfo.m_startWorldTransform = startTransform;
btRigidBody* body = new btRigidBody(rbInfo);
body->setRollingFriction(0.03);
+ body->setSpinningFriction(0.03);
body->setFriction(1);
body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
diff --git a/examples/RenderingExamples/TinyRendererSetup.cpp b/examples/RenderingExamples/TinyRendererSetup.cpp
index a38b13abd..caec7c41a 100644
--- a/examples/RenderingExamples/TinyRendererSetup.cpp
+++ b/examples/RenderingExamples/TinyRendererSetup.cpp
@@ -23,6 +23,7 @@ struct TinyRendererSetupInternalData
TGAImage m_rgbColorBuffer;
b3AlignedObjectArray m_depthBuffer;
+ b3AlignedObjectArray m_shadowBuffer;
b3AlignedObjectArray m_segmentationMaskBuffer;
@@ -53,6 +54,7 @@ struct TinyRendererSetupInternalData
m_animateRenderer(0)
{
m_depthBuffer.resize(m_width*m_height);
+ m_shadowBuffer.resize(m_width*m_height);
// m_segmentationMaskBuffer.resize(m_width*m_height);
}
@@ -152,7 +154,7 @@ TinyRendererSetup::TinyRendererSetup(struct GUIHelperInterface* gui)
const char* fileName = "textured_sphere_smooth.obj";
fileName = "cube.obj";
-
+ fileName = "torus/torus_with_plane.obj";
{
@@ -188,6 +190,7 @@ TinyRendererSetup::TinyRendererSetup(struct GUIHelperInterface* gui)
TinyRenderObjectData* ob = new TinyRenderObjectData(
m_internalData->m_rgbColorBuffer,
m_internalData->m_depthBuffer,
+ &m_internalData->m_shadowBuffer,
&m_internalData->m_segmentationMaskBuffer,
m_internalData->m_renderObjects.size());
@@ -328,6 +331,7 @@ void TinyRendererSetup::stepSimulation(float deltaTime)
{
m_internalData->m_rgbColorBuffer.set(x,y,clearColor);
m_internalData->m_depthBuffer[x+y*m_internalData->m_width] = -1e30f;
+ m_internalData->m_shadowBuffer[x+y*m_internalData->m_width] = -1e30f;
}
}
@@ -339,7 +343,46 @@ void TinyRendererSetup::stepSimulation(float deltaTime)
render->getActiveCamera()->getCameraViewMatrix(viewMat);
render->getActiveCamera()->getCameraProjectionMatrix(projMat);
-
+ for (int o=0;om_internalData->m_renderObjects.size();o++)
+ {
+
+ const btTransform& tr = m_internalData->m_transforms[o];
+ tr.getOpenGLMatrix(modelMat2);
+
+
+ for (int i=0;i<4;i++)
+ {
+ for (int j=0;j<4;j++)
+ {
+ m_internalData->m_renderObjects[o]->m_modelMatrix[i][j] = float(modelMat2[i+4*j]);
+ m_internalData->m_renderObjects[o]->m_viewMatrix[i][j] = viewMat[i+4*j];
+ m_internalData->m_renderObjects[o]->m_projectionMatrix[i][j] = projMat[i+4*j];
+
+ btVector3 lightDirWorld;
+ switch (m_app->getUpAxis())
+ {
+ case 1:
+ lightDirWorld = btVector3(-50.f,100,30);
+ break;
+ case 2:
+ lightDirWorld = btVector3(-50.f,30,100);
+ break;
+ default:{}
+ };
+
+ m_internalData->m_renderObjects[o]->m_lightDirWorld = lightDirWorld.normalized();
+
+ btVector3 lightColor(1.0,1.0,1.0);
+ m_internalData->m_renderObjects[o]->m_lightColor = lightColor;
+
+ m_internalData->m_renderObjects[o]->m_lightDistance = 10.0;
+ m_internalData->m_renderObjects[o]->m_lightAmbientCoeff = 0.6;
+ m_internalData->m_renderObjects[o]->m_lightDiffuseCoeff = 0.35;
+ m_internalData->m_renderObjects[o]->m_lightSpecularCoeff = 0.05;
+ }
+ }
+ TinyRenderer::renderObjectDepth(*m_internalData->m_renderObjects[o]);
+ }
for (int o=0;om_internalData->m_renderObjects.size();o++)
{
@@ -369,6 +412,14 @@ void TinyRendererSetup::stepSimulation(float deltaTime)
};
m_internalData->m_renderObjects[o]->m_lightDirWorld = lightDirWorld.normalized();
+
+ btVector3 lightColor(1.0,1.0,1.0);
+ m_internalData->m_renderObjects[o]->m_lightColor = lightColor;
+
+ m_internalData->m_renderObjects[o]->m_lightDistance = 10.0;
+ m_internalData->m_renderObjects[o]->m_lightAmbientCoeff = 0.6;
+ m_internalData->m_renderObjects[o]->m_lightDiffuseCoeff = 0.35;
+ m_internalData->m_renderObjects[o]->m_lightSpecularCoeff = 0.05;
}
}
diff --git a/examples/RoboticsLearning/GripperGraspExample.cpp b/examples/RoboticsLearning/GripperGraspExample.cpp
index 37e6c06a0..71e32924d 100644
--- a/examples/RoboticsLearning/GripperGraspExample.cpp
+++ b/examples/RoboticsLearning/GripperGraspExample.cpp
@@ -343,7 +343,6 @@ public:
slider.m_maxVal=1;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
}
- if (1)
{
b3RobotSimLoadFileArgs args("");
args.m_fileName = "gripper/wsg50_one_motor_gripper_new.sdf";
@@ -374,12 +373,10 @@ public:
}
}
-
- if (1)
{
b3RobotSimLoadFileArgs args("");
args.m_fileName = "plane.urdf";
- args.m_startPosition.setValue(0,0,0);
+ args.m_startPosition.setValue(0,0,-0.2);
args.m_startOrientation.setEulerZYX(0,0,0);
args.m_forceOverrideFixedBase = true;
args.m_useMultiBody = true;
@@ -388,7 +385,7 @@ public:
}
m_robotSim.setGravity(b3MakeVector3(0,0,-10));
- m_robotSim.loadBunny();
+ m_robotSim.loadBunny(0.1,0.1,0.02);
b3JointInfo revoluteJoint1;
revoluteJoint1.m_parentFrame[0] = -0.055;
@@ -431,6 +428,46 @@ public:
m_robotSim.createJoint(0, 2, 0, 4, &revoluteJoint1);
m_robotSim.createJoint(0, 3, 0, 6, &revoluteJoint2);
}
+
+ if ((m_options & eSOFTBODY_MULTIBODY_COUPLING)!=0)
+ {
+ {
+ b3RobotSimLoadFileArgs args("");
+ args.m_fileName = "kuka_iiwa/model_free_base.urdf";
+ args.m_startPosition.setValue(0,1.0,2.0);
+ args.m_startOrientation.setEulerZYX(0,0,1.57);
+ args.m_forceOverrideFixedBase = false;
+ args.m_useMultiBody = true;
+ b3RobotSimLoadFileResults results;
+ m_robotSim.loadFile(args,results);
+
+ int kukaId = results.m_uniqueObjectIds[0];
+ int numJoints = m_robotSim.getNumJoints(kukaId);
+ b3Printf("numJoints = %d",numJoints);
+
+ for (int i=0;im_physicsClient));
if (b3CanSubmitCommand(m_data->m_physicsClient))
{
- statusHandle = b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClient, b3CreateJoint(m_data->m_physicsClient, parentBodyIndex, parentJointIndex, childBodyIndex, childJointIndex, jointInfo));
+ statusHandle = b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClient, b3InitCreateUserConstraintCommand(m_data->m_physicsClient, parentBodyIndex, parentJointIndex, childBodyIndex, childJointIndex, jointInfo));
}
}
@@ -893,7 +910,8 @@ bool b3RobotSimAPI::connect(GUIHelperInterface* guiHelper)
}
else
{
- m_data->m_clientServerDirect = new PhysicsDirect();
+ PhysicsServerCommandProcessor* sdk = new PhysicsServerCommandProcessor;
+ m_data->m_clientServerDirect = new PhysicsDirect(sdk);
bool connected = m_data->m_clientServerDirect->connect(guiHelper);
m_data->m_physicsClient = (b3PhysicsClientHandle)m_data->m_clientServerDirect;
@@ -1000,8 +1018,11 @@ void b3RobotSimAPI::getLinkState(int bodyUniqueId, int linkIndex, double* worldP
}
}
-void b3RobotSimAPI::loadBunny()
+void b3RobotSimAPI::loadBunny(double scale, double mass, double collisionMargin)
{
b3SharedMemoryCommandHandle command = b3LoadBunnyCommandInit(m_data->m_physicsClient);
+ b3LoadBunnySetScale(command, scale);
+ b3LoadBunnySetMass(command, mass);
+ b3LoadBunnySetCollisionMargin(command, collisionMargin);
b3SubmitClientCommand(m_data->m_physicsClient, command);
-}
\ No newline at end of file
+}
diff --git a/examples/RoboticsLearning/b3RobotSimAPI.h b/examples/RoboticsLearning/b3RobotSimAPI.h
index 882817384..886aafcad 100644
--- a/examples/RoboticsLearning/b3RobotSimAPI.h
+++ b/examples/RoboticsLearning/b3RobotSimAPI.h
@@ -165,7 +165,7 @@ public:
void getLinkState(int bodyUniqueId, int linkIndex, double* worldPosition, double* worldOrientation);
- void loadBunny();
+ void loadBunny(double scale, double mass, double collisionMargin);
};
#endif //B3_ROBOT_SIM_API_H
diff --git a/examples/RollingFrictionDemo/RollingFrictionDemo.cpp b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp
index 7e53be9b0..65a2404d3 100644
--- a/examples/RollingFrictionDemo/RollingFrictionDemo.cpp
+++ b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp
@@ -123,8 +123,8 @@ void RollingFrictionDemo::initPhysics()
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
- body->setFriction(1);
- body->setRollingFriction(1);
+ body->setFriction(.5);
+
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
@@ -153,8 +153,7 @@ void RollingFrictionDemo::initPhysics()
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
- body->setFriction(1);
- body->setRollingFriction(1);
+ body->setFriction(.1);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
@@ -217,7 +216,8 @@ void RollingFrictionDemo::initPhysics()
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
body->setFriction(1.f);
- body->setRollingFriction(.3);
+ body->setRollingFriction(.1);
+ body->setSpinningFriction(0.1);
body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
diff --git a/examples/SharedMemory/IKTrajectoryHelper.cpp b/examples/SharedMemory/IKTrajectoryHelper.cpp
index 13bd8a2ad..a9af38164 100644
--- a/examples/SharedMemory/IKTrajectoryHelper.cpp
+++ b/examples/SharedMemory/IKTrajectoryHelper.cpp
@@ -18,7 +18,6 @@ struct IKTrajectoryHelperInternalData
VectorRn m_nullSpaceVelocity;
b3AlignedObjectArray m_ikNodes;
- Jacobian* m_ikJacobian;
IKTrajectoryHelperInternalData()
{
@@ -48,23 +47,21 @@ bool IKTrajectoryHelper::computeIK(const double endEffectorTargetPosition[3],
{
bool useAngularPart = (ikMethod==IK2_VEL_DLS_WITH_ORIENTATION || ikMethod==IK2_VEL_DLS_WITH_ORIENTATION_NULLSPACE) ? true : false;
- m_data->m_ikJacobian = new Jacobian(useAngularPart,numQ);
-
-// Reset(m_ikTree,m_ikJacobian);
+ Jacobian ikJacobian(useAngularPart,numQ);
- m_data->m_ikJacobian->Reset();
+ ikJacobian.Reset();
bool UseJacobianTargets1 = false;
if ( UseJacobianTargets1 ) {
- m_data->m_ikJacobian->SetJtargetActive();
+ ikJacobian.SetJtargetActive();
}
else {
- m_data->m_ikJacobian->SetJendActive();
+ ikJacobian.SetJendActive();
}
VectorR3 targets;
targets.Set(endEffectorTargetPosition[0],endEffectorTargetPosition[1],endEffectorTargetPosition[2]);
- m_data->m_ikJacobian->ComputeJacobian(&targets); // Set up Jacobian and deltaS vectors
+ ikJacobian.ComputeJacobian(&targets); // Set up Jacobian and deltaS vectors
// Set one end effector world position from Bullet
VectorRn deltaS(3);
@@ -112,8 +109,8 @@ bool IKTrajectoryHelper::computeIK(const double endEffectorTargetPosition[3],
completeJacobian.Set(i+3,j,angular_jacobian[i*numQ+j]);
}
}
- m_data->m_ikJacobian->SetDeltaS(deltaC);
- m_data->m_ikJacobian->SetJendTrans(completeJacobian);
+ ikJacobian.SetDeltaS(deltaC);
+ ikJacobian.SetJendTrans(completeJacobian);
} else
{
VectorRn deltaC(3);
@@ -126,53 +123,53 @@ bool IKTrajectoryHelper::computeIK(const double endEffectorTargetPosition[3],
completeJacobian.Set(i,j,linear_jacobian[i*numQ+j]);
}
}
- m_data->m_ikJacobian->SetDeltaS(deltaC);
- m_data->m_ikJacobian->SetJendTrans(completeJacobian);
+ ikJacobian.SetDeltaS(deltaC);
+ ikJacobian.SetJendTrans(completeJacobian);
}
}
// Calculate the change in theta values
switch (ikMethod) {
case IK2_JACOB_TRANS:
- m_data->m_ikJacobian->CalcDeltaThetasTranspose(); // Jacobian transpose method
+ ikJacobian.CalcDeltaThetasTranspose(); // Jacobian transpose method
break;
case IK2_DLS:
case IK2_VEL_DLS:
case IK2_VEL_DLS_WITH_ORIENTATION:
- m_data->m_ikJacobian->CalcDeltaThetasDLS(); // Damped least squares method
+ ikJacobian.CalcDeltaThetasDLS(); // Damped least squares method
break;
case IK2_VEL_DLS_WITH_NULLSPACE:
case IK2_VEL_DLS_WITH_ORIENTATION_NULLSPACE:
assert(m_data->m_nullSpaceVelocity.GetLength()==numQ);
- m_data->m_ikJacobian->CalcDeltaThetasDLSwithNullspace(m_data->m_nullSpaceVelocity);
+ ikJacobian.CalcDeltaThetasDLSwithNullspace(m_data->m_nullSpaceVelocity);
break;
case IK2_DLS_SVD:
- m_data->m_ikJacobian->CalcDeltaThetasDLSwithSVD();
+ ikJacobian.CalcDeltaThetasDLSwithSVD();
break;
case IK2_PURE_PSEUDO:
- m_data->m_ikJacobian->CalcDeltaThetasPseudoinverse(); // Pure pseudoinverse method
+ ikJacobian.CalcDeltaThetasPseudoinverse(); // Pure pseudoinverse method
break;
case IK2_SDLS:
- m_data->m_ikJacobian->CalcDeltaThetasSDLS(); // Selectively damped least squares method
+ ikJacobian.CalcDeltaThetasSDLS(); // Selectively damped least squares method
break;
default:
- m_data->m_ikJacobian->ZeroDeltaThetas();
+ ikJacobian.ZeroDeltaThetas();
break;
}
// Use for velocity IK, update theta dot
- //m_data->m_ikJacobian->UpdateThetaDot();
+ //ikJacobian.UpdateThetaDot();
// Use for position IK, incrementally update theta
- //m_data->m_ikJacobian->UpdateThetas();
+ //ikJacobian.UpdateThetas();
// Apply the change in the theta values
- //m_data->m_ikJacobian->UpdatedSClampValue(&targets);
+ //ikJacobian.UpdatedSClampValue(&targets);
for (int i=0;im_ikJacobian->dTheta[i] + q_current[i];
+ q_new[i] = ikJacobian.dTheta[i] + q_current[i];
// Use for position IK
//q_new[i] = m_data->m_ikNodes[i]->GetTheta();
@@ -203,4 +200,4 @@ bool IKTrajectoryHelper::computeNullspaceVel(int numQ, const double* q_current,
}
}
return true;
-}
\ No newline at end of file
+}
diff --git a/examples/SharedMemory/PhysicsClient.h b/examples/SharedMemory/PhysicsClient.h
index f028f537f..e1c20cadb 100644
--- a/examples/SharedMemory/PhysicsClient.h
+++ b/examples/SharedMemory/PhysicsClient.h
@@ -48,6 +48,8 @@ public:
virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData)=0;
+ virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects) = 0;
+
virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo) = 0;
};
diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp
index 71ac91832..a9d217c3e 100644
--- a/examples/SharedMemory/PhysicsClientC_API.cpp
+++ b/examples/SharedMemory/PhysicsClientC_API.cpp
@@ -58,23 +58,108 @@ b3SharedMemoryCommandHandle b3LoadUrdfCommandInit(b3PhysicsClientHandle physClie
b3Assert(cl);
b3Assert(cl->canSubmitCommand());
-
- struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
- b3Assert(command);
- command->m_type = CMD_LOAD_URDF;
- int len = strlen(urdfFileName);
- if (lencanSubmitCommand())
{
- strcpy(command->m_urdfArguments.m_urdfFileName,urdfFileName);
- } else
- {
- command->m_urdfArguments.m_urdfFileName[0] = 0;
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_LOAD_URDF;
+ int len = strlen(urdfFileName);
+ if (len < MAX_URDF_FILENAME_LENGTH)
+ {
+ strcpy(command->m_urdfArguments.m_urdfFileName, urdfFileName);
+ }
+ else
+ {
+ command->m_urdfArguments.m_urdfFileName[0] = 0;
+ }
+ command->m_updateFlags = URDF_ARGS_FILE_NAME;
+
+ return (b3SharedMemoryCommandHandle)command;
}
- command->m_updateFlags = URDF_ARGS_FILE_NAME;
-
- return (b3SharedMemoryCommandHandle) command;
+ return 0;
}
+b3SharedMemoryCommandHandle b3LoadBulletCommandInit(b3PhysicsClientHandle physClient, const char* fileName)
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+
+ if (cl->canSubmitCommand())
+ {
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_LOAD_BULLET;
+ int len = strlen(fileName);
+ if (len < MAX_URDF_FILENAME_LENGTH)
+ {
+ strcpy(command->m_fileArguments.m_fileName, fileName);
+ }
+ else
+ {
+ command->m_fileArguments.m_fileName[0] = 0;
+ }
+ command->m_updateFlags = 0;
+
+ return (b3SharedMemoryCommandHandle)command;
+ }
+ return 0;
+}
+
+b3SharedMemoryCommandHandle b3SaveBulletCommandInit(b3PhysicsClientHandle physClient, const char* fileName)
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+
+ if (cl->canSubmitCommand())
+ {
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_SAVE_BULLET;
+ int len = strlen(fileName);
+ if (len < MAX_URDF_FILENAME_LENGTH)
+ {
+ strcpy(command->m_fileArguments.m_fileName, fileName);
+ }
+ else
+ {
+ command->m_fileArguments.m_fileName[0] = 0;
+ }
+ command->m_updateFlags = 0;
+
+ return (b3SharedMemoryCommandHandle)command;
+ }
+ return 0;
+}
+b3SharedMemoryCommandHandle b3LoadMJCFCommandInit(b3PhysicsClientHandle physClient, const char* fileName)
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+
+ if (cl->canSubmitCommand())
+ {
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_LOAD_MJCF;
+ int len = strlen(fileName);
+ if (len < MAX_URDF_FILENAME_LENGTH)
+ {
+ strcpy(command->m_fileArguments.m_fileName, fileName);
+ }
+ else
+ {
+ command->m_fileArguments.m_fileName[0] = 0;
+ }
+ command->m_updateFlags = 0;
+
+ return (b3SharedMemoryCommandHandle)command;
+ }
+ return 0;
+}
+
+
b3SharedMemoryCommandHandle b3LoadBunnyCommandInit(b3PhysicsClientHandle physClient)
{
PhysicsClient* cl = (PhysicsClient* ) physClient;
@@ -89,6 +174,33 @@ b3SharedMemoryCommandHandle b3LoadBunnyCommandInit(b3PhysicsClientHandle physCli
return (b3SharedMemoryCommandHandle) command;
}
+int b3LoadBunnySetScale(b3SharedMemoryCommandHandle commandHandle, double scale)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command->m_type == CMD_LOAD_BUNNY);
+ command->m_loadBunnyArguments.m_scale = scale;
+ command->m_updateFlags |= LOAD_BUNNY_UPDATE_SCALE;
+ return 0;
+}
+
+int b3LoadBunnySetMass(b3SharedMemoryCommandHandle commandHandle, double mass)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command->m_type == CMD_LOAD_BUNNY);
+ command->m_loadBunnyArguments.m_mass = mass;
+ command->m_updateFlags |= LOAD_BUNNY_UPDATE_MASS;
+ return 0;
+}
+
+int b3LoadBunnySetCollisionMargin(b3SharedMemoryCommandHandle commandHandle, double collisionMargin)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command->m_type == CMD_LOAD_BUNNY);
+ command->m_loadBunnyArguments.m_collisionMargin = collisionMargin;
+ command->m_updateFlags |= LOAD_BUNNY_UPDATE_COLLISION_MARGIN;
+ return 0;
+}
+
int b3LoadUrdfCommandSetUseMultiBody(b3SharedMemoryCommandHandle commandHandle, int useMultiBody)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
@@ -116,35 +228,52 @@ int b3LoadUrdfCommandSetUseFixedBase(b3SharedMemoryCommandHandle commandHandle,
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
b3Assert(command->m_type == CMD_LOAD_URDF);
- command->m_updateFlags |=URDF_ARGS_USE_FIXED_BASE;
- command->m_urdfArguments.m_useFixedBase = useFixedBase;
-
- return 0;
+ if (command && (command->m_type == CMD_LOAD_URDF))
+ {
+ command->m_updateFlags |= URDF_ARGS_USE_FIXED_BASE;
+ command->m_urdfArguments.m_useFixedBase = useFixedBase;
+ return 0;
+ }
+ return -1;
}
int b3LoadUrdfCommandSetStartPosition(b3SharedMemoryCommandHandle commandHandle, double startPosX,double startPosY,double startPosZ)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
- b3Assert(command->m_type == CMD_LOAD_URDF);
- command->m_urdfArguments.m_initialPosition[0] = startPosX;
- command->m_urdfArguments.m_initialPosition[1] = startPosY;
- command->m_urdfArguments.m_initialPosition[2] = startPosZ;
- command->m_updateFlags|=URDF_ARGS_INITIAL_POSITION;
- return 0;
+ if (command)
+ {
+ b3Assert(command->m_type == CMD_LOAD_URDF);
+ if (command->m_type == CMD_LOAD_URDF)
+ {
+ command->m_urdfArguments.m_initialPosition[0] = startPosX;
+ command->m_urdfArguments.m_initialPosition[1] = startPosY;
+ command->m_urdfArguments.m_initialPosition[2] = startPosZ;
+ command->m_updateFlags |= URDF_ARGS_INITIAL_POSITION;
+ }
+ return 0;
+ }
+ return -1;
}
int b3LoadUrdfCommandSetStartOrientation(b3SharedMemoryCommandHandle commandHandle, double startOrnX,double startOrnY,double startOrnZ, double startOrnW)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
- b3Assert(command->m_type == CMD_LOAD_URDF);
- command->m_urdfArguments.m_initialOrientation[0] = startOrnX;
- command->m_urdfArguments.m_initialOrientation[1] = startOrnY;
- command->m_urdfArguments.m_initialOrientation[2] = startOrnZ;
- command->m_urdfArguments.m_initialOrientation[3] = startOrnW;
- command->m_updateFlags|=URDF_ARGS_INITIAL_ORIENTATION;
- return 0;
+ if (command)
+ {
+ b3Assert(command->m_type == CMD_LOAD_URDF);
+ if (command->m_type == CMD_LOAD_URDF)
+ {
+ command->m_urdfArguments.m_initialOrientation[0] = startOrnX;
+ command->m_urdfArguments.m_initialOrientation[1] = startOrnY;
+ command->m_urdfArguments.m_initialOrientation[2] = startOrnZ;
+ command->m_urdfArguments.m_initialOrientation[3] = startOrnW;
+ command->m_updateFlags |= URDF_ARGS_INITIAL_ORIENTATION;
+ }
+ return 0;
+ }
+ return -1;
}
b3SharedMemoryCommandHandle b3InitPhysicsParamCommand(b3PhysicsClientHandle physClient)
@@ -174,7 +303,7 @@ int b3PhysicsParamSetRealTimeSimulation(b3SharedMemoryCommandHandle commandH
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command->m_type == CMD_SEND_PHYSICS_SIMULATION_PARAMETERS);
- command->m_physSimParamArgs.m_allowRealTimeSimulation = enableRealTimeSimulation;
+ command->m_physSimParamArgs.m_allowRealTimeSimulation = (enableRealTimeSimulation!=0);
command->m_updateFlags |= SIM_PARAM_UPDATE_REAL_TIME_SIMULATION;
return 0;
}
@@ -188,6 +317,26 @@ int b3PhysicsParamSetInternalSimFlags(b3SharedMemoryCommandHandle commandHan
return 0;
}
+int b3PhysicsParamSetUseSplitImpulse(b3SharedMemoryCommandHandle commandHandle, int useSplitImpulse)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command->m_type == CMD_SEND_PHYSICS_SIMULATION_PARAMETERS);
+
+ command->m_physSimParamArgs.m_useSplitImpulse = useSplitImpulse;
+ command->m_updateFlags |= SIM_PARAM_UPDATE_USE_SPLIT_IMPULSE;
+ return 0;
+}
+
+int b3PhysicsParamSetSplitImpulsePenetrationThreshold(b3SharedMemoryCommandHandle commandHandle, double splitImpulsePenetrationThreshold)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command->m_type == CMD_SEND_PHYSICS_SIMULATION_PARAMETERS);
+
+ command->m_physSimParamArgs.m_splitImpulsePenetrationThreshold = splitImpulsePenetrationThreshold;
+ command->m_updateFlags |= SIM_PARAM_UPDATE_SPLIT_IMPULSE_PENETRATION_THRESHOLD;
+ return 0;
+}
+
int b3PhysicsParamSetNumSolverIterations(b3SharedMemoryCommandHandle commandHandle, int numSolverIterations)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
@@ -543,6 +692,40 @@ int b3CreatePoseCommandSetBaseOrientation(b3SharedMemoryCommandHandle commandHan
return 0;
}
+int b3CreatePoseCommandSetBaseLinearVelocity(b3SharedMemoryCommandHandle commandHandle, double linVel[3])
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_INIT_POSE);
+ command->m_updateFlags |= INIT_POSE_HAS_BASE_LINEAR_VELOCITY;
+ command->m_initPoseArgs.m_hasInitialStateQdot[0] = 1;
+ command->m_initPoseArgs.m_hasInitialStateQdot[1] = 1;
+ command->m_initPoseArgs.m_hasInitialStateQdot[2] = 1;
+
+ command->m_initPoseArgs.m_initialStateQdot[0] = linVel[0];
+ command->m_initPoseArgs.m_initialStateQdot[1] = linVel[1];
+ command->m_initPoseArgs.m_initialStateQdot[2] = linVel[2];
+
+ return 0;
+}
+
+int b3CreatePoseCommandSetBaseAngularVelocity(b3SharedMemoryCommandHandle commandHandle, double angVel[3])
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_INIT_POSE);
+ command->m_updateFlags |= INIT_POSE_HAS_BASE_ANGULAR_VELOCITY;
+ command->m_initPoseArgs.m_hasInitialStateQdot[3] = 1;
+ command->m_initPoseArgs.m_hasInitialStateQdot[4] = 1;
+ command->m_initPoseArgs.m_hasInitialStateQdot[5] = 1;
+
+ command->m_initPoseArgs.m_initialStateQdot[3] = angVel[0];
+ command->m_initPoseArgs.m_initialStateQdot[4] = angVel[1];
+ command->m_initPoseArgs.m_initialStateQdot[5] = angVel[2];
+
+ return 0;
+}
+
int b3CreatePoseCommandSetJointPositions(b3SharedMemoryCommandHandle commandHandle, int numJointPositions, const double* jointPositions)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
@@ -557,6 +740,8 @@ int b3CreatePoseCommandSetJointPositions(b3SharedMemoryCommandHandle commandHand
return 0;
}
+
+
int b3CreatePoseCommandSetJointPosition(b3PhysicsClientHandle physClient, b3SharedMemoryCommandHandle commandHandle, int jointIndex, double jointPosition)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
@@ -621,20 +806,11 @@ int b3CreateSensorEnableIMUForLink(b3SharedMemoryCommandHandle commandHandle, in
}
-b3PhysicsClientHandle b3ConnectSharedMemory(int key)
-{
-
- PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory();
- ///client should never create shared memory, only the server does
- cl->setSharedMemoryKey(key);
- cl->connect();
- return (b3PhysicsClientHandle ) cl;
-}
-
void b3DisconnectSharedMemory(b3PhysicsClientHandle physClient)
{
PhysicsClient* cl = (PhysicsClient* ) physClient;
+ cl->disconnectSharedMemory();
delete cl;
}
@@ -673,6 +849,7 @@ int b3GetStatusBodyIndices(b3SharedMemoryStatusHandle statusHandle, int* bodyInd
{
switch (status->m_type)
{
+ case CMD_BULLET_LOADING_COMPLETED:
case CMD_SDF_LOADING_COMPLETED:
{
int i,maxBodies;
@@ -772,22 +949,34 @@ int b3SubmitClientCommand(b3PhysicsClientHandle physClient, const b3SharedMemory
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
PhysicsClient* cl = (PhysicsClient* ) physClient;
- return (int)cl->submitClientCommand(*command);
+ b3Assert(command);
+ b3Assert(cl);
+ if (command && cl)
+ {
+ return (int)cl->submitClientCommand(*command);
+ }
+ return -1;
+
}
b3SharedMemoryStatusHandle b3SubmitClientCommandAndWaitStatus(b3PhysicsClientHandle physClient, const b3SharedMemoryCommandHandle commandHandle)
{
- int timeout = 1024*1024*1024;
- b3SharedMemoryStatusHandle statusHandle=0;
-
- b3SubmitClientCommand(physClient,commandHandle);
-
- while ((statusHandle==0) && (timeout-- > 0))
- {
- statusHandle =b3ProcessServerStatus(physClient);
- }
- return (b3SharedMemoryStatusHandle) statusHandle;
-
+ int timeout = 1024 * 1024 * 1024;
+ b3SharedMemoryStatusHandle statusHandle = 0;
+ b3Assert(commandHandle);
+ b3Assert(physClient);
+ if (physClient && commandHandle)
+ {
+ b3SubmitClientCommand(physClient, commandHandle);
+
+ while ((statusHandle == 0) && (timeout-- > 0))
+ {
+ statusHandle = b3ProcessServerStatus(physClient);
+ }
+ return (b3SharedMemoryStatusHandle)statusHandle;
+ }
+
+ return 0;
}
@@ -827,7 +1016,9 @@ int b3GetJointInfo(b3PhysicsClientHandle physClient, int bodyIndex, int jointInd
return cl->getJointInfo(bodyIndex, jointIndex, *info);
}
-b3SharedMemoryCommandHandle b3CreateJoint(b3PhysicsClientHandle physClient, int parentBodyIndex, int parentJointIndex, int childBodyIndex, int childJointIndex, struct b3JointInfo* info)
+
+
+b3SharedMemoryCommandHandle b3InitCreateUserConstraintCommand(b3PhysicsClientHandle physClient, int parentBodyIndex, int parentJointIndex, int childBodyIndex, int childJointIndex, struct b3JointInfo* info)
{
PhysicsClient* cl = (PhysicsClient* ) physClient;
b3Assert(cl);
@@ -835,22 +1026,52 @@ b3SharedMemoryCommandHandle b3CreateJoint(b3PhysicsClientHandle physClient, int
struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
b3Assert(command);
- command->m_type = CMD_CREATE_JOINT;
- command->m_createJointArguments.m_parentBodyIndex = parentBodyIndex;
- command->m_createJointArguments.m_parentJointIndex = parentJointIndex;
- command->m_createJointArguments.m_childBodyIndex = childBodyIndex;
- command->m_createJointArguments.m_childJointIndex = childJointIndex;
+ command->m_type = CMD_USER_CONSTRAINT;
+ command->m_updateFlags = USER_CONSTRAINT_ADD_CONSTRAINT;
+
+ command->m_userConstraintArguments.m_parentBodyIndex = parentBodyIndex;
+ command->m_userConstraintArguments.m_parentJointIndex = parentJointIndex;
+ command->m_userConstraintArguments.m_childBodyIndex = childBodyIndex;
+ command->m_userConstraintArguments.m_childJointIndex = childJointIndex;
for (int i = 0; i < 7; ++i) {
- command->m_createJointArguments.m_parentFrame[i] = info->m_parentFrame[i];
- command->m_createJointArguments.m_childFrame[i] = info->m_childFrame[i];
+ command->m_userConstraintArguments.m_parentFrame[i] = info->m_parentFrame[i];
+ command->m_userConstraintArguments.m_childFrame[i] = info->m_childFrame[i];
}
for (int i = 0; i < 3; ++i) {
- command->m_createJointArguments.m_jointAxis[i] = info->m_jointAxis[i];
+ command->m_userConstraintArguments.m_jointAxis[i] = info->m_jointAxis[i];
}
- command->m_createJointArguments.m_jointType = info->m_jointType;
+ command->m_userConstraintArguments.m_jointType = info->m_jointType;
return (b3SharedMemoryCommandHandle)command;
}
+b3SharedMemoryCommandHandle b3InitRemoveUserConstraintCommand(b3PhysicsClientHandle physClient, int userConstraintUniqueId)
+{
+ PhysicsClient* cl = (PhysicsClient* ) physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+
+ command->m_type = CMD_USER_CONSTRAINT;
+ command->m_updateFlags = USER_CONSTRAINT_REMOVE_CONSTRAINT;
+ command->m_userConstraintArguments.m_userConstraintUniqueId = userConstraintUniqueId;
+ return (b3SharedMemoryCommandHandle)command;
+}
+int b3GetStatusUserConstraintUniqueId(b3SharedMemoryStatusHandle statusHandle)
+{
+ const SharedMemoryStatus* status = (const SharedMemoryStatus* ) statusHandle;
+ b3Assert(status);
+ b3Assert(status->m_type == CMD_USER_CONSTRAINT_COMPLETED);
+ if (status && status->m_type == CMD_USER_CONSTRAINT_COMPLETED)
+ {
+ return status->m_userConstraintResultArgs.m_userConstraintUniqueId;
+ }
+
+ return -1;
+
+}
+
+
b3SharedMemoryCommandHandle b3PickBody(b3PhysicsClientHandle physClient, double rayFromWorldX,
double rayFromWorldY, double rayFromWorldZ,
double rayToWorldX, double rayToWorldY, double rayToWorldZ)
@@ -930,6 +1151,147 @@ void b3GetDebugLines(b3PhysicsClientHandle physClient, struct b3DebugLines* l
}
+
+/// Add/remove user-specific debug lines and debug text messages
+b3SharedMemoryCommandHandle b3InitUserDebugDrawAddLine3D(b3PhysicsClientHandle physClient, double fromXYZ[3], double toXYZ[3], double colorRGB[3], double lineWidth, double lifeTime)
+{
+ PhysicsClient* cl = (PhysicsClient* ) physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type =CMD_USER_DEBUG_DRAW;
+ command->m_updateFlags = USER_DEBUG_HAS_LINE; //USER_DEBUG_HAS_TEXT
+
+ command->m_userDebugDrawArgs.m_debugLineFromXYZ[0] = fromXYZ[0];
+ command->m_userDebugDrawArgs.m_debugLineFromXYZ[1] = fromXYZ[1];
+ command->m_userDebugDrawArgs.m_debugLineFromXYZ[2] = fromXYZ[2];
+
+ command->m_userDebugDrawArgs.m_debugLineToXYZ[0] = toXYZ[0];
+ command->m_userDebugDrawArgs.m_debugLineToXYZ[1] = toXYZ[1];
+ command->m_userDebugDrawArgs.m_debugLineToXYZ[2] = toXYZ[2];
+
+ command->m_userDebugDrawArgs.m_debugLineColorRGB[0] = colorRGB[0];
+ command->m_userDebugDrawArgs.m_debugLineColorRGB[1] = colorRGB[1];
+ command->m_userDebugDrawArgs.m_debugLineColorRGB[2] = colorRGB[2];
+
+ command->m_userDebugDrawArgs.m_lineWidth = lineWidth;
+ command->m_userDebugDrawArgs.m_lifeTime = lifeTime;
+
+ return (b3SharedMemoryCommandHandle) command;
+}
+
+b3SharedMemoryCommandHandle b3InitUserDebugDrawAddText3D(b3PhysicsClientHandle physClient, const char* txt, double positionXYZ[3], double colorRGB[3], double textSize, double lifeTime)
+{
+
+ PhysicsClient* cl = (PhysicsClient* ) physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type =CMD_USER_DEBUG_DRAW;
+ command->m_updateFlags = USER_DEBUG_HAS_TEXT;
+
+ int len = strlen(txt);
+ if (lenm_userDebugDrawArgs.m_text,txt);
+ } else
+ {
+ command->m_userDebugDrawArgs.m_text[0] = 0;
+ }
+ command->m_userDebugDrawArgs.m_textPositionXYZ[0] = positionXYZ[0];
+ command->m_userDebugDrawArgs.m_textPositionXYZ[1] = positionXYZ[1];
+ command->m_userDebugDrawArgs.m_textPositionXYZ[2] = positionXYZ[2];
+
+ command->m_userDebugDrawArgs.m_textColorRGB[0] = colorRGB[0];
+ command->m_userDebugDrawArgs.m_textColorRGB[1] = colorRGB[1];
+ command->m_userDebugDrawArgs.m_textColorRGB[2] = colorRGB[2];
+
+ command->m_userDebugDrawArgs.m_textSize = textSize;
+
+ command->m_userDebugDrawArgs.m_lifeTime = lifeTime;
+
+ return (b3SharedMemoryCommandHandle) command;
+}
+
+b3SharedMemoryCommandHandle b3InitUserDebugDrawRemove(b3PhysicsClientHandle physClient, int debugItemUniqueId)
+{
+ PhysicsClient* cl = (PhysicsClient* ) physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type =CMD_USER_DEBUG_DRAW;
+ command->m_updateFlags = USER_DEBUG_REMOVE_ONE_ITEM;
+ command->m_userDebugDrawArgs.m_removeItemUniqueId = debugItemUniqueId;
+ return (b3SharedMemoryCommandHandle) command;
+
+}
+
+b3SharedMemoryCommandHandle b3InitUserDebugDrawRemoveAll(b3PhysicsClientHandle physClient)
+{
+ PhysicsClient* cl = (PhysicsClient* ) physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type =CMD_USER_DEBUG_DRAW;
+ command->m_updateFlags = USER_DEBUG_REMOVE_ALL;
+ return (b3SharedMemoryCommandHandle) command;
+}
+
+int b3GetDebugItemUniqueId(b3SharedMemoryStatusHandle statusHandle)
+{
+ const SharedMemoryStatus* status = (const SharedMemoryStatus*)statusHandle;
+ btAssert(status->m_type == CMD_USER_DEBUG_DRAW_COMPLETED);
+ if (status->m_type != CMD_USER_DEBUG_DRAW_COMPLETED)
+ return -1;
+
+ return status->m_userDebugDrawArgs.m_debugItemUniqueId;
+}
+
+b3SharedMemoryCommandHandle b3InitDebugDrawingCommand(b3PhysicsClientHandle physClient)
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_USER_DEBUG_DRAW;
+ command->m_updateFlags = 0;
+ return (b3SharedMemoryCommandHandle)command;
+}
+
+
+
+void b3SetDebugObjectColor(b3SharedMemoryCommandHandle commandHandle, int objectUniqueId, int linkIndex, double objectColorRGB[3])
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_USER_DEBUG_DRAW);
+ command->m_updateFlags |= USER_DEBUG_SET_CUSTOM_OBJECT_COLOR;
+ command->m_userDebugDrawArgs.m_objectUniqueId = objectUniqueId;
+ command->m_userDebugDrawArgs.m_linkIndex = linkIndex;
+ command->m_userDebugDrawArgs.m_objectDebugColorRGB[0] = objectColorRGB[0];
+ command->m_userDebugDrawArgs.m_objectDebugColorRGB[1] = objectColorRGB[1];
+ command->m_userDebugDrawArgs.m_objectDebugColorRGB[2] = objectColorRGB[2];
+}
+
+void b3RemoveDebugObjectColor(b3SharedMemoryCommandHandle commandHandle, int objectUniqueId, int linkIndex)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_USER_DEBUG_DRAW);
+ command->m_updateFlags |= USER_DEBUG_REMOVE_CUSTOM_OBJECT_COLOR;
+ command->m_userDebugDrawArgs.m_objectUniqueId = objectUniqueId;
+ command->m_userDebugDrawArgs.m_linkIndex = linkIndex;
+
+}
+
+
+
+
///request an image from a simulated camera, using a software renderer.
b3SharedMemoryCommandHandle b3InitRequestCameraImage(b3PhysicsClientHandle physClient)
{
@@ -966,209 +1328,300 @@ void b3RequestCameraImageSetCameraMatrices(b3SharedMemoryCommandHandle commandHa
command->m_updateFlags |= REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES;
}
+void b3RequestCameraImageSetLightDirection(b3SharedMemoryCommandHandle commandHandle, const float lightDirection[3])
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ for (int i = 0; i<3; i++)
+ {
+ command->m_requestPixelDataArguments.m_lightDirection[i] = lightDirection[i];
+ }
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_LIGHT_DIRECTION;
+}
+
+void b3RequestCameraImageSetLightColor(b3SharedMemoryCommandHandle commandHandle, const float lightColor[3])
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ for (int i = 0; i<3; i++)
+ {
+ command->m_requestPixelDataArguments.m_lightColor[i] = lightColor[i];
+ }
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_LIGHT_COLOR;
+}
+
+void b3RequestCameraImageSetLightDistance(b3SharedMemoryCommandHandle commandHandle, float lightDistance)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ command->m_requestPixelDataArguments.m_lightDistance = lightDistance;
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_LIGHT_DISTANCE;
+}
+
+void b3RequestCameraImageSetLightAmbientCoeff(b3SharedMemoryCommandHandle commandHandle, float lightAmbientCoeff)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ command->m_requestPixelDataArguments.m_lightAmbientCoeff = lightAmbientCoeff;
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_AMBIENT_COEFF;
+}
+
+void b3RequestCameraImageSetLightDiffuseCoeff(b3SharedMemoryCommandHandle commandHandle, float lightDiffuseCoeff)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ command->m_requestPixelDataArguments.m_lightDiffuseCoeff = lightDiffuseCoeff;
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_DIFFUSE_COEFF;
+}
+
+void b3RequestCameraImageSetLightSpecularCoeff(b3SharedMemoryCommandHandle commandHandle, float lightSpecularCoeff)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ command->m_requestPixelDataArguments.m_lightSpecularCoeff = lightSpecularCoeff;
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_SPECULAR_COEFF;
+}
+
+void b3RequestCameraImageSetShadow(b3SharedMemoryCommandHandle commandHandle, int hasShadow)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
+ command->m_requestPixelDataArguments.m_hasShadow = hasShadow;
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_SET_SHADOW;
+}
+
+void b3ComputeViewMatrixFromPositions(const float cameraPosition[3], const float cameraTargetPosition[3], const float cameraUp[3], float viewMatrix[16])
+{
+ b3Vector3 eye = b3MakeVector3(cameraPosition[0], cameraPosition[1], cameraPosition[2]);
+ b3Vector3 center = b3MakeVector3(cameraTargetPosition[0], cameraTargetPosition[1], cameraTargetPosition[2]);
+ b3Vector3 up = b3MakeVector3(cameraUp[0], cameraUp[1], cameraUp[2]);
+ b3Vector3 f = (center - eye).normalized();
+ b3Vector3 u = up.normalized();
+ b3Vector3 s = (f.cross(u)).normalized();
+ u = s.cross(f);
+
+ viewMatrix[0 * 4 + 0] = s.x;
+ viewMatrix[1 * 4 + 0] = s.y;
+ viewMatrix[2 * 4 + 0] = s.z;
+
+ viewMatrix[0 * 4 + 1] = u.x;
+ viewMatrix[1 * 4 + 1] = u.y;
+ viewMatrix[2 * 4 + 1] = u.z;
+
+ viewMatrix[0 * 4 + 2] = -f.x;
+ viewMatrix[1 * 4 + 2] = -f.y;
+ viewMatrix[2 * 4 + 2] = -f.z;
+
+ viewMatrix[0 * 4 + 3] = 0.f;
+ viewMatrix[1 * 4 + 3] = 0.f;
+ viewMatrix[2 * 4 + 3] = 0.f;
+
+ viewMatrix[3 * 4 + 0] = -s.dot(eye);
+ viewMatrix[3 * 4 + 1] = -u.dot(eye);
+ viewMatrix[3 * 4 + 2] = f.dot(eye);
+ viewMatrix[3 * 4 + 3] = 1.f;
+}
+
+
+void b3ComputeViewMatrixFromYawPitchRoll(const float cameraTargetPosition[3], float distance, float yaw, float pitch, float roll, int upAxis, float viewMatrix[16])
+{
+ b3Vector3 camUpVector;
+ b3Vector3 camForward;
+ b3Vector3 camPos;
+ b3Vector3 camTargetPos = b3MakeVector3(cameraTargetPosition[0], cameraTargetPosition[1], cameraTargetPosition[2]);
+ b3Vector3 eyePos = b3MakeVector3(0, 0, 0);
+
+ int forwardAxis(-1);
+
+ {
+
+ switch (upAxis)
+ {
+
+ case 1:
+ {
+
+
+ forwardAxis = 0;
+ eyePos[forwardAxis] = -distance;
+ camForward = b3MakeVector3(eyePos[0], eyePos[1], eyePos[2]);
+ if (camForward.length2() < B3_EPSILON)
+ {
+ camForward.setValue(1.f, 0.f, 0.f);
+ }
+ else
+ {
+ camForward.normalize();
+ }
+ b3Scalar rollRad = roll * b3Scalar(0.01745329251994329547);
+ b3Quaternion rollRot(camForward, rollRad);
+
+ camUpVector = b3QuatRotate(rollRot, b3MakeVector3(0, 1, 0));
+ //gLightPos = b3MakeVector3(-50.f,100,30);
+ break;
+ }
+ case 2:
+ {
+
+
+ forwardAxis = 1;
+ eyePos[forwardAxis] = -distance;
+ camForward = b3MakeVector3(eyePos[0], eyePos[1], eyePos[2]);
+ if (camForward.length2() < B3_EPSILON)
+ {
+ camForward.setValue(1.f, 0.f, 0.f);
+ }
+ else
+ {
+ camForward.normalize();
+ }
+
+ b3Scalar rollRad = roll * b3Scalar(0.01745329251994329547);
+ b3Quaternion rollRot(camForward, rollRad);
+
+ camUpVector = b3QuatRotate(rollRot, b3MakeVector3(0, 0, 1));
+ //gLightPos = b3MakeVector3(-50.f,30,100);
+ break;
+ }
+ default:
+ {
+ //b3Assert(0);
+ return;
+ }
+ };
+ }
+
+
+ b3Scalar yawRad = yaw * b3Scalar(0.01745329251994329547);// rads per deg
+ b3Scalar pitchRad = pitch * b3Scalar(0.01745329251994329547);// rads per deg
+
+ b3Quaternion pitchRot(camUpVector, pitchRad);
+
+ b3Vector3 right = camUpVector.cross(camForward);
+ b3Quaternion yawRot(right, -yawRad);
+
+ eyePos = b3Matrix3x3(pitchRot) * b3Matrix3x3(yawRot) * eyePos;
+ camPos = eyePos;
+ camPos += camTargetPos;
+
+ float camPosf[4] = { camPos[0],camPos[1],camPos[2],0 };
+ float camPosTargetf[4] = { camTargetPos[0],camTargetPos[1],camTargetPos[2],0 };
+ float camUpf[4] = { camUpVector[0],camUpVector[1],camUpVector[2],0 };
+
+ b3ComputeViewMatrixFromPositions(camPosf, camPosTargetf, camUpf,viewMatrix);
+
+}
+
+
+void b3ComputeProjectionMatrix(float left, float right, float bottom, float top, float nearVal, float farVal, float projectionMatrix[16])
+{
+ projectionMatrix[0 * 4 + 0] = (float(2) * nearVal) / (right - left);
+ projectionMatrix[0 * 4 + 1] = float(0);
+ projectionMatrix[0 * 4 + 2] = float(0);
+ projectionMatrix[0 * 4 + 3] = float(0);
+
+ projectionMatrix[1 * 4 + 0] = float(0);
+ projectionMatrix[1 * 4 + 1] = (float(2) * nearVal) / (top - bottom);
+ projectionMatrix[1 * 4 + 2] = float(0);
+ projectionMatrix[1 * 4 + 3] = float(0);
+
+ projectionMatrix[2 * 4 + 0] = (right + left) / (right - left);
+ projectionMatrix[2 * 4 + 1] = (top + bottom) / (top - bottom);
+ projectionMatrix[2 * 4 + 2] = -(farVal + nearVal) / (farVal - nearVal);
+ projectionMatrix[2 * 4 + 3] = float(-1);
+
+ projectionMatrix[3 * 4 + 0] = float(0);
+ projectionMatrix[3 * 4 + 1] = float(0);
+ projectionMatrix[3 * 4 + 2] = -(float(2) * farVal * nearVal) / (farVal - nearVal);
+ projectionMatrix[3 * 4 + 3] = float(0);
+}
+
+
+void b3ComputeProjectionMatrixFOV(float fov, float aspect, float nearVal, float farVal, float projectionMatrix[16])
+{
+ float yScale = 1.0 / tan((3.141592538 / 180.0) * fov / 2);
+ float xScale = yScale / aspect;
+
+ projectionMatrix[0 * 4 + 0] = xScale;
+ projectionMatrix[0 * 4 + 1] = float(0);
+ projectionMatrix[0 * 4 + 2] = float(0);
+ projectionMatrix[0 * 4 + 3] = float(0);
+
+ projectionMatrix[1 * 4 + 0] = float(0);
+ projectionMatrix[1 * 4 + 1] = yScale;
+ projectionMatrix[1 * 4 + 2] = float(0);
+ projectionMatrix[1 * 4 + 3] = float(0);
+
+ projectionMatrix[2 * 4 + 0] = 0;
+ projectionMatrix[2 * 4 + 1] = 0;
+ projectionMatrix[2 * 4 + 2] = (nearVal + farVal) / (nearVal - farVal);
+ projectionMatrix[2 * 4 + 3] = float(-1);
+
+ projectionMatrix[3 * 4 + 0] = float(0);
+ projectionMatrix[3 * 4 + 1] = float(0);
+ projectionMatrix[3 * 4 + 2] = (float(2) * farVal * nearVal) / (nearVal - farVal);
+ projectionMatrix[3 * 4 + 3] = float(0);
+}
+
+
void b3RequestCameraImageSetViewMatrix2(b3SharedMemoryCommandHandle commandHandle, const float cameraTargetPosition[3], float distance, float yaw, float pitch, float roll, int upAxis)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
- b3Vector3 camUpVector;
- b3Vector3 camForward;
- b3Vector3 camPos;
- b3Vector3 camTargetPos = b3MakeVector3(cameraTargetPosition[0],cameraTargetPosition[1],cameraTargetPosition[2]);
- b3Vector3 eyePos = b3MakeVector3(0,0,0);
-
- int forwardAxis(-1);
-
- {
-
- switch (upAxis)
- {
-
- case 1:
- {
-
-
- forwardAxis = 0;
- eyePos[forwardAxis] = -distance;
- camForward = b3MakeVector3(eyePos[0],eyePos[1],eyePos[2]);
- if (camForward.length2() < B3_EPSILON)
- {
- camForward.setValue(1.f,0.f,0.f);
- } else
- {
- camForward.normalize();
- }
- b3Scalar rollRad = roll * b3Scalar(0.01745329251994329547);
- b3Quaternion rollRot(camForward,rollRad);
-
- camUpVector = b3QuatRotate(rollRot,b3MakeVector3(0,1,0));
- //gLightPos = b3MakeVector3(-50.f,100,30);
- break;
- }
- case 2:
- {
-
-
- forwardAxis = 1;
- eyePos[forwardAxis] = -distance;
- camForward = b3MakeVector3(eyePos[0],eyePos[1],eyePos[2]);
- if (camForward.length2() < B3_EPSILON)
- {
- camForward.setValue(1.f,0.f,0.f);
- } else
- {
- camForward.normalize();
- }
-
- b3Scalar rollRad = roll * b3Scalar(0.01745329251994329547);
- b3Quaternion rollRot(camForward,rollRad);
-
- camUpVector = b3QuatRotate(rollRot,b3MakeVector3(0,0,1));
- //gLightPos = b3MakeVector3(-50.f,30,100);
- break;
- }
- default:
- {
- //b3Assert(0);
- return;
- }
- };
- }
-
-
- b3Scalar yawRad = yaw * b3Scalar(0.01745329251994329547);// rads per deg
- b3Scalar pitchRad = pitch * b3Scalar(0.01745329251994329547);// rads per deg
-
- b3Quaternion pitchRot(camUpVector,pitchRad);
-
- b3Vector3 right = camUpVector.cross(camForward);
- b3Quaternion yawRot(right,-yawRad);
-
-
-
- eyePos = b3Matrix3x3(pitchRot) * b3Matrix3x3(yawRot) * eyePos;
- camPos = eyePos;
- camPos += camTargetPos;
-
- float camPosf[4] = {camPos[0],camPos[1],camPos[2],0};
- float camPosTargetf[4] = {camTargetPos[0],camTargetPos[1],camTargetPos[2],0};
- float camUpf[4] = {camUpVector[0],camUpVector[1],camUpVector[2],0};
-
- b3RequestCameraImageSetViewMatrix(commandHandle,camPosf,camPosTargetf,camUpf);
+
+ b3ComputeViewMatrixFromYawPitchRoll(cameraTargetPosition, distance, yaw, pitch, roll, upAxis, command->m_requestPixelDataArguments.m_viewMatrix);
+ command->m_updateFlags |= REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES;
}
+
+
+
+
void b3RequestCameraImageSetViewMatrix(b3SharedMemoryCommandHandle commandHandle, const float cameraPosition[3], const float cameraTargetPosition[3], const float cameraUp[3])
{
- b3Vector3 eye = b3MakeVector3(cameraPosition[0], cameraPosition[1], cameraPosition[2]);
- b3Vector3 center = b3MakeVector3(cameraTargetPosition[0], cameraTargetPosition[1], cameraTargetPosition[2]);
- b3Vector3 up = b3MakeVector3(cameraUp[0], cameraUp[1], cameraUp[2]);
- b3Vector3 f = (center - eye).normalized();
- b3Vector3 u = up.normalized();
- b3Vector3 s = (f.cross(u)).normalized();
- u = s.cross(f);
-
- float viewMatrix[16];
-
- viewMatrix[0*4+0] = s.x;
- viewMatrix[1*4+0] = s.y;
- viewMatrix[2*4+0] = s.z;
-
- viewMatrix[0*4+1] = u.x;
- viewMatrix[1*4+1] = u.y;
- viewMatrix[2*4+1] = u.z;
-
- viewMatrix[0*4+2] =-f.x;
- viewMatrix[1*4+2] =-f.y;
- viewMatrix[2*4+2] =-f.z;
-
- viewMatrix[0*4+3] = 0.f;
- viewMatrix[1*4+3] = 0.f;
- viewMatrix[2*4+3] = 0.f;
-
- viewMatrix[3*4+0] = -s.dot(eye);
- viewMatrix[3*4+1] = -u.dot(eye);
- viewMatrix[3*4+2] = f.dot(eye);
- viewMatrix[3*4+3] = 1.f;
+ float viewMatrix[16];
+ b3ComputeViewMatrixFromPositions(cameraPosition, cameraTargetPosition, cameraUp, viewMatrix);
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
- for (int i=0;i<16;i++)
- {
- command->m_requestPixelDataArguments.m_viewMatrix[i] = viewMatrix[i];
- }
+
+ b3ComputeViewMatrixFromPositions(cameraPosition, cameraTargetPosition, cameraUp, command->m_requestPixelDataArguments.m_viewMatrix);
+
command->m_updateFlags |= REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES;
}
void b3RequestCameraImageSetProjectionMatrix(b3SharedMemoryCommandHandle commandHandle, float left, float right, float bottom, float top, float nearVal, float farVal)
{
- float frustum[16];
-
- frustum[0*4+0] = (float(2) * nearVal) / (right - left);
- frustum[0*4+1] = float(0);
- frustum[0*4+2] = float(0);
- frustum[0*4+3] = float(0);
-
- frustum[1*4+0] = float(0);
- frustum[1*4+1] = (float(2) * nearVal) / (top - bottom);
- frustum[1*4+2] = float(0);
- frustum[1*4+3] = float(0);
-
- frustum[2*4+0] = (right + left) / (right - left);
- frustum[2*4+1] = (top + bottom) / (top - bottom);
- frustum[2*4+2] = -(farVal + nearVal) / (farVal - nearVal);
- frustum[2*4+3] = float(-1);
-
- frustum[3*4+0] = float(0);
- frustum[3*4+1] = float(0);
- frustum[3*4+2] = -(float(2) * farVal * nearVal) / (farVal - nearVal);
- frustum[3*4+3] = float(0);
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
- for (int i=0;i<16;i++)
- {
- command->m_requestPixelDataArguments.m_projectionMatrix[i] = frustum[i];
- }
+
+ b3ComputeProjectionMatrix(left, right, bottom, top, nearVal, farVal, command->m_requestPixelDataArguments.m_projectionMatrix);
+
command->m_updateFlags |= REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES;
}
void b3RequestCameraImageSetFOVProjectionMatrix(b3SharedMemoryCommandHandle commandHandle, float fov, float aspect, float nearVal, float farVal)
{
- float yScale = 1.0 / tan((3.141592538 / 180.0) * fov / 2);
- float xScale = yScale / aspect;
-
- float frustum[16];
-
- frustum[0*4+0] = xScale;
- frustum[0*4+1] = float(0);
- frustum[0*4+2] = float(0);
- frustum[0*4+3] = float(0);
-
- frustum[1*4+0] = float(0);
- frustum[1*4+1] = yScale;
- frustum[1*4+2] = float(0);
- frustum[1*4+3] = float(0);
-
- frustum[2*4+0] = 0;
- frustum[2*4+1] = 0;
- frustum[2*4+2] = (nearVal + farVal) / (nearVal - farVal);
- frustum[2*4+3] = float(-1);
-
- frustum[3*4+0] = float(0);
- frustum[3*4+1] = float(0);
- frustum[3*4+2] = (float(2) * farVal * nearVal) / (nearVal - farVal);
- frustum[3*4+3] = float(0);
+
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
b3Assert(command);
b3Assert(command->m_type == CMD_REQUEST_CAMERA_IMAGE_DATA);
- for (int i=0;i<16;i++)
- {
- command->m_requestPixelDataArguments.m_projectionMatrix[i] = frustum[i];
- }
+
+ b3ComputeProjectionMatrixFOV(fov, aspect, nearVal, farVal, command->m_requestPixelDataArguments.m_projectionMatrix);
+
command->m_updateFlags |= REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES;
}
@@ -1203,6 +1656,8 @@ b3SharedMemoryCommandHandle b3InitRequestContactPointInformation(b3PhysicsClient
command->m_requestContactPointArguments.m_startingContactPointIndex = 0;
command->m_requestContactPointArguments.m_objectAIndexFilter = -1;
command->m_requestContactPointArguments.m_objectBIndexFilter = -1;
+ command->m_requestContactPointArguments.m_linkIndexAIndexFilter = -2;
+ command->m_requestContactPointArguments.m_linkIndexBIndexFilter = -2;
command->m_updateFlags = 0;
return (b3SharedMemoryCommandHandle) command;
}
@@ -1215,6 +1670,37 @@ void b3SetContactFilterBodyA(b3SharedMemoryCommandHandle commandHandle, int body
command->m_requestContactPointArguments.m_objectAIndexFilter = bodyUniqueIdA;
}
+void b3SetContactFilterLinkA(b3SharedMemoryCommandHandle commandHandle, int linkIndexA)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CONTACT_POINT_INFORMATION);
+ command->m_updateFlags |= CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_A_FILTER;
+ command->m_requestContactPointArguments.m_linkIndexAIndexFilter= linkIndexA;
+}
+
+void b3SetContactFilterLinkB(b3SharedMemoryCommandHandle commandHandle, int linkIndexB)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CONTACT_POINT_INFORMATION);
+ command->m_updateFlags |= CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_B_FILTER;
+ command->m_requestContactPointArguments.m_linkIndexBIndexFilter = linkIndexB;
+}
+
+void b3SetClosestDistanceFilterLinkA(b3SharedMemoryCommandHandle commandHandle, int linkIndexA)
+{
+ b3SetContactFilterLinkA(commandHandle, linkIndexA);
+}
+
+void b3SetClosestDistanceFilterLinkB(b3SharedMemoryCommandHandle commandHandle, int linkIndexB)
+{
+ b3SetContactFilterLinkB(commandHandle, linkIndexB);
+}
+
+
+
+
void b3SetContactFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdB)
{
struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
@@ -1223,7 +1709,69 @@ void b3SetContactFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int body
command->m_requestContactPointArguments.m_objectBIndexFilter = bodyUniqueIdB;
}
-void b3SetContactFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdB);
+
+///compute the closest points between two bodies
+b3SharedMemoryCommandHandle b3InitClosestDistanceQuery(b3PhysicsClientHandle physClient)
+{
+ b3SharedMemoryCommandHandle commandHandle =b3InitRequestContactPointInformation(physClient);
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CONTACT_POINT_INFORMATION);
+ command->m_updateFlags = CMD_REQUEST_CONTACT_POINT_HAS_QUERY_MODE;
+ command->m_requestContactPointArguments.m_mode = CONTACT_QUERY_MODE_COMPUTE_CLOSEST_POINTS;
+ return commandHandle;
+}
+
+void b3SetClosestDistanceFilterBodyA(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdA)
+{
+ b3SetContactFilterBodyA(commandHandle,bodyUniqueIdA);
+}
+
+void b3SetClosestDistanceFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdB)
+{
+ b3SetContactFilterBodyB(commandHandle,bodyUniqueIdB);
+}
+
+void b3SetClosestDistanceThreshold(b3SharedMemoryCommandHandle commandHandle, double distance)
+{
+ struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle;
+ b3Assert(command);
+ b3Assert(command->m_type == CMD_REQUEST_CONTACT_POINT_INFORMATION);
+ command->m_updateFlags += CMD_REQUEST_CONTACT_POINT_HAS_CLOSEST_DISTANCE_THRESHOLD;
+ command->m_requestContactPointArguments.m_closestDistanceThreshold = distance;
+}
+
+
+///get all the bodies that touch a given axis aligned bounding box specified in world space (min and max coordinates)
+b3SharedMemoryCommandHandle b3InitAABBOverlapQuery(b3PhysicsClientHandle physClient, const double aabbMin[3], const double aabbMax[3])
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ b3Assert(cl);
+ b3Assert(cl->canSubmitCommand());
+ struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand();
+ b3Assert(command);
+ command->m_type = CMD_REQUEST_AABB_OVERLAP;
+ command->m_updateFlags = 0;
+ command->m_requestOverlappingObjectsArgs.m_startingOverlappingObjectIndex = 0;
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMin[0] = aabbMin[0];
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMin[1] = aabbMin[1];
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMin[2] = aabbMin[2];
+
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMax[0] = aabbMax[0];
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMax[1] = aabbMax[1];
+ command->m_requestOverlappingObjectsArgs.m_aabbQueryMax[2] = aabbMax[2];
+ return (b3SharedMemoryCommandHandle)command;
+}
+
+void b3GetAABBOverlapResults(b3PhysicsClientHandle physClient, struct b3AABBOverlapData* data)
+{
+ PhysicsClient* cl = (PhysicsClient*)physClient;
+ if (cl)
+ {
+ cl->getCachedOverlappingObjects(data);
+ }
+}
+
void b3GetContactPointInformation(b3PhysicsClientHandle physClient, struct b3ContactInformation* contactPointData)
@@ -1235,6 +1783,11 @@ void b3GetContactPointInformation(b3PhysicsClientHandle physClient, struct b3Con
}
}
+void b3GetClosestPointInformation(b3PhysicsClientHandle physClient, struct b3ContactInformation* contactPointInfo)
+{
+ b3GetContactPointInformation(physClient,contactPointInfo);
+}
+
//request visual shape information
@@ -1428,6 +1981,7 @@ b3SharedMemoryCommandHandle b3CalculateJacobianCommandInit(b3PhysicsClientHandle
return (b3SharedMemoryCommandHandle)command;
}
+
int b3GetStatusJacobian(b3SharedMemoryStatusHandle statusHandle, double* linearJacobian, double* angularJacobian)
{
const SharedMemoryStatus* status = (const SharedMemoryStatus*)statusHandle;
@@ -1580,4 +2134,4 @@ int b3GetStatusInverseKinematicsJointPositions(b3SharedMemoryStatusHandle status
}
return true;
-}
\ No newline at end of file
+}
diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h
index 9fa0cbbfb..97b6a14a6 100644
--- a/examples/SharedMemory/PhysicsClientC_API.h
+++ b/examples/SharedMemory/PhysicsClientC_API.h
@@ -11,14 +11,18 @@ B3_DECLARE_HANDLE(b3SharedMemoryCommandHandle);
B3_DECLARE_HANDLE(b3SharedMemoryStatusHandle);
+///There are several connection methods, see following header files:
+#include "PhysicsClientSharedMemory_C_API.h"
+#include "PhysicsClientSharedMemory2_C_API.h"
+#include "PhysicsDirectC_API.h"
+#include "PhysicsClientUDP_C_API.h"
+#include "SharedMemoryInProcessPhysicsC_API.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-///b3ConnectSharedMemory will connect to a physics server over shared memory, so
-///make sure to start the server first.
-///and a way to spawn an OpenGL 3D GUI physics server and connect (b3CreateInProcessPhysicsServerAndConnect)
-b3PhysicsClientHandle b3ConnectSharedMemory(int key);
+
///b3DisconnectSharedMemory will disconnect the client from the server and cleanup memory.
void b3DisconnectSharedMemory(b3PhysicsClientHandle physClient);
@@ -68,33 +72,86 @@ int b3GetNumJoints(b3PhysicsClientHandle physClient, int bodyIndex);
///given a body and joint index, return the joint information. See b3JointInfo in SharedMemoryPublic.h
int b3GetJointInfo(b3PhysicsClientHandle physClient, int bodyIndex, int jointIndex, struct b3JointInfo* info);
-b3SharedMemoryCommandHandle b3CreateJoint(b3PhysicsClientHandle physClient, int parentBodyIndex, int parentJointIndex, int childBodyIndex, int childJointIndex, struct b3JointInfo* info);
+b3SharedMemoryCommandHandle b3InitCreateUserConstraintCommand(b3PhysicsClientHandle physClient, int parentBodyIndex, int parentJointIndex, int childBodyIndex, int childJointIndex, struct b3JointInfo* info);
+int b3GetStatusUserConstraintUniqueId(b3SharedMemoryStatusHandle statusHandle);
+b3SharedMemoryCommandHandle b3InitRemoveUserConstraintCommand(b3PhysicsClientHandle physClient, int userConstraintUniqueId);
-///Request debug lines for debug visualization. The flags in debugMode are the same as used in Bullet
+///Request physics debug lines for debug visualization. The flags in debugMode are the same as used in Bullet
///See btIDebugDraw::DebugDrawModes in Bullet/src/LinearMath/btIDebugDraw.h
b3SharedMemoryCommandHandle b3InitRequestDebugLinesCommand(b3PhysicsClientHandle physClient, int debugMode);
-///Get the pointers to the debug line information, after b3InitRequestDebugLinesCommand returns
+///Get the pointers to the physics debug line information, after b3InitRequestDebugLinesCommand returns
///status CMD_DEBUG_LINES_COMPLETED
void b3GetDebugLines(b3PhysicsClientHandle physClient, struct b3DebugLines* lines);
+/// Add/remove user-specific debug lines and debug text messages
+b3SharedMemoryCommandHandle b3InitUserDebugDrawAddLine3D(b3PhysicsClientHandle physClient, double fromXYZ[3], double toXYZ[3], double colorRGB[3], double lineWidth, double lifeTime);
+b3SharedMemoryCommandHandle b3InitUserDebugDrawAddText3D(b3PhysicsClientHandle physClient, const char* txt, double positionXYZ[3], double colorRGB[3], double textSize, double lifeTime);
+b3SharedMemoryCommandHandle b3InitUserDebugDrawRemove(b3PhysicsClientHandle physClient, int debugItemUniqueId);
+b3SharedMemoryCommandHandle b3InitUserDebugDrawRemoveAll(b3PhysicsClientHandle physClient);
+
+b3SharedMemoryCommandHandle b3InitDebugDrawingCommand(b3PhysicsClientHandle physClient);
+void b3SetDebugObjectColor(b3SharedMemoryCommandHandle commandHandle, int objectUniqueId, int linkIndex, double objectColorRGB[3]);
+void b3RemoveDebugObjectColor(b3SharedMemoryCommandHandle commandHandle, int objectUniqueId, int linkIndex);
+
+///All debug items unique Ids are positive: a negative unique Id means failure.
+int b3GetDebugItemUniqueId(b3SharedMemoryStatusHandle statusHandle);
+
+
///request an image from a simulated camera, using a software renderer.
b3SharedMemoryCommandHandle b3InitRequestCameraImage(b3PhysicsClientHandle physClient);
void b3RequestCameraImageSetCameraMatrices(b3SharedMemoryCommandHandle command, float viewMatrix[16], float projectionMatrix[16]);
-void b3RequestCameraImageSetViewMatrix(b3SharedMemoryCommandHandle command, const float cameraPosition[3], const float cameraTargetPosition[3], const float cameraUp[3]);
-void b3RequestCameraImageSetViewMatrix2(b3SharedMemoryCommandHandle commandHandle, const float cameraTargetPosition[3], float distance, float yaw, float pitch, float roll, int upAxis);
-void b3RequestCameraImageSetProjectionMatrix(b3SharedMemoryCommandHandle command, float left, float right, float bottom, float top, float nearVal, float farVal);
-void b3RequestCameraImageSetFOVProjectionMatrix(b3SharedMemoryCommandHandle command, float fov, float aspect, float nearVal, float farVal);
void b3RequestCameraImageSetPixelResolution(b3SharedMemoryCommandHandle command, int width, int height );
+void b3RequestCameraImageSetLightDirection(b3SharedMemoryCommandHandle commandHandle, const float lightDirection[3]);
+void b3RequestCameraImageSetLightColor(b3SharedMemoryCommandHandle commandHandle, const float lightColor[3]);
+void b3RequestCameraImageSetLightDistance(b3SharedMemoryCommandHandle commandHandle, float lightDistance);
+void b3RequestCameraImageSetLightAmbientCoeff(b3SharedMemoryCommandHandle commandHandle, float lightAmbientCoeff);
+void b3RequestCameraImageSetLightDiffuseCoeff(b3SharedMemoryCommandHandle commandHandle, float lightDiffuseCoeff);
+void b3RequestCameraImageSetLightSpecularCoeff(b3SharedMemoryCommandHandle commandHandle, float lightSpecularCoeff);
+void b3RequestCameraImageSetShadow(b3SharedMemoryCommandHandle commandHandle, int hasShadow);
void b3RequestCameraImageSelectRenderer(b3SharedMemoryCommandHandle commandHandle, int renderer);
void b3GetCameraImageData(b3PhysicsClientHandle physClient, struct b3CameraImageData* imageData);
+///compute a view matrix, helper function for b3RequestCameraImageSetCameraMatrices
+void b3ComputeViewMatrixFromPositions(const float cameraPosition[3], const float cameraTargetPosition[3], const float cameraUp[3], float viewMatrix[16]);
+void b3ComputeViewMatrixFromYawPitchRoll(const float cameraTargetPosition[3], float distance, float yaw, float pitch, float roll, int upAxis, float viewMatrix[16]);
+
+///compute a projection matrix, helper function for b3RequestCameraImageSetCameraMatrices
+void b3ComputeProjectionMatrix(float left, float right, float bottom, float top, float nearVal, float farVal, float projectionMatrix[16]);
+void b3ComputeProjectionMatrixFOV(float fov, float aspect, float nearVal, float farVal, float projectionMatrix[16]);
+
+
+/* obsolete, please use b3ComputeViewProjectionMatrices */
+void b3RequestCameraImageSetViewMatrix(b3SharedMemoryCommandHandle command, const float cameraPosition[3], const float cameraTargetPosition[3], const float cameraUp[3]);
+/* obsolete, please use b3ComputeViewProjectionMatrices */
+void b3RequestCameraImageSetViewMatrix2(b3SharedMemoryCommandHandle commandHandle, const float cameraTargetPosition[3], float distance, float yaw, float pitch, float roll, int upAxis);
+/* obsolete, please use b3ComputeViewProjectionMatrices */
+void b3RequestCameraImageSetProjectionMatrix(b3SharedMemoryCommandHandle command, float left, float right, float bottom, float top, float nearVal, float farVal);
+/* obsolete, please use b3ComputeViewProjectionMatrices */
+void b3RequestCameraImageSetFOVProjectionMatrix(b3SharedMemoryCommandHandle command, float fov, float aspect, float nearVal, float farVal);
+
+
///request an contact point information
b3SharedMemoryCommandHandle b3InitRequestContactPointInformation(b3PhysicsClientHandle physClient);
void b3SetContactFilterBodyA(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdA);
void b3SetContactFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdB);
+void b3SetContactFilterLinkA(b3SharedMemoryCommandHandle commandHandle, int linkIndexA);
+void b3SetContactFilterLinkB(b3SharedMemoryCommandHandle commandHandle, int linkIndexB);
void b3GetContactPointInformation(b3PhysicsClientHandle physClient, struct b3ContactInformation* contactPointInfo);
+///compute the closest points between two bodies
+b3SharedMemoryCommandHandle b3InitClosestDistanceQuery(b3PhysicsClientHandle physClient);
+void b3SetClosestDistanceFilterBodyA(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdA);
+void b3SetClosestDistanceFilterLinkA(b3SharedMemoryCommandHandle commandHandle, int linkIndexA);
+void b3SetClosestDistanceFilterBodyB(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueIdB);
+void b3SetClosestDistanceFilterLinkB(b3SharedMemoryCommandHandle commandHandle, int linkIndexB);
+void b3SetClosestDistanceThreshold(b3SharedMemoryCommandHandle commandHandle, double distance);
+void b3GetClosestPointInformation(b3PhysicsClientHandle physClient, struct b3ContactInformation* contactPointInfo);
+
+///get all the bodies that touch a given axis aligned bounding box specified in world space (min and max coordinates)
+b3SharedMemoryCommandHandle b3InitAABBOverlapQuery(b3PhysicsClientHandle physClient, const double aabbMin[3],const double aabbMax[3]);
+void b3GetAABBOverlapResults(b3PhysicsClientHandle physClient, struct b3AABBOverlapData* data);
+
//request visual shape information
b3SharedMemoryCommandHandle b3InitRequestVisualShapeInformation(b3PhysicsClientHandle physClient, int bodyUniqueIdA);
void b3GetVisualShapeInformation(b3PhysicsClientHandle physClient, struct b3VisualShapeInformation* visualShapeInfo);
@@ -109,6 +166,9 @@ int b3PhysicsParamSetDefaultContactERP(b3SharedMemoryCommandHandle commandHandle
int b3PhysicsParamSetNumSubSteps(b3SharedMemoryCommandHandle commandHandle, int numSubSteps);
int b3PhysicsParamSetRealTimeSimulation(b3SharedMemoryCommandHandle commandHandle, int enableRealTimeSimulation);
int b3PhysicsParamSetNumSolverIterations(b3SharedMemoryCommandHandle commandHandle, int numSolverIterations);
+int b3PhysicsParamSetUseSplitImpulse(b3SharedMemoryCommandHandle commandHandle, int useSplitImpulse);
+int b3PhysicsParamSetSplitImpulsePenetrationThreshold(b3SharedMemoryCommandHandle commandHandle, double splitImpulsePenetrationThreshold);
+
//b3PhysicsParamSetInternalSimFlags is for internal/temporary/easter-egg/experimental demo purposes
//Use at own risk: magic things may or my not happen when calling this API
@@ -128,6 +188,11 @@ int b3LoadUrdfCommandSetStartOrientation(b3SharedMemoryCommandHandle commandHand
int b3LoadUrdfCommandSetUseMultiBody(b3SharedMemoryCommandHandle commandHandle, int useMultiBody);
int b3LoadUrdfCommandSetUseFixedBase(b3SharedMemoryCommandHandle commandHandle, int useFixedBase);
+b3SharedMemoryCommandHandle b3LoadBulletCommandInit(b3PhysicsClientHandle physClient, const char* fileName);
+b3SharedMemoryCommandHandle b3SaveBulletCommandInit(b3PhysicsClientHandle physClient, const char* fileName);
+b3SharedMemoryCommandHandle b3LoadMJCFCommandInit(b3PhysicsClientHandle physClient, const char* fileName);
+
+
///compute the forces to achieve an acceleration, given a state q and qdot using inverse dynamics
b3SharedMemoryCommandHandle b3CalculateInverseDynamicsCommandInit(b3PhysicsClientHandle physClient, int bodyIndex,
@@ -199,6 +264,9 @@ int b3CreateBoxCommandSetColorRGBA(b3SharedMemoryCommandHandle commandHandle, do
b3SharedMemoryCommandHandle b3CreatePoseCommandInit(b3PhysicsClientHandle physClient, int bodyIndex);
int b3CreatePoseCommandSetBasePosition(b3SharedMemoryCommandHandle commandHandle, double startPosX,double startPosY,double startPosZ);
int b3CreatePoseCommandSetBaseOrientation(b3SharedMemoryCommandHandle commandHandle, double startOrnX,double startOrnY,double startOrnZ, double startOrnW);
+int b3CreatePoseCommandSetBaseLinearVelocity(b3SharedMemoryCommandHandle commandHandle, double linVel[3]);
+int b3CreatePoseCommandSetBaseAngularVelocity(b3SharedMemoryCommandHandle commandHandle, double angVel[3]);
+
int b3CreatePoseCommandSetJointPositions(b3SharedMemoryCommandHandle commandHandle, int numJointPositions, const double* jointPositions);
int b3CreatePoseCommandSetJointPosition(b3PhysicsClientHandle physClient, b3SharedMemoryCommandHandle commandHandle, int jointIndex, double jointPosition);
@@ -228,7 +296,11 @@ b3SharedMemoryCommandHandle b3ApplyExternalForceCommandInit(b3PhysicsClientHandl
void b3ApplyExternalForce(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueId, int linkId, const double force[3], const double position[3], int flags);
void b3ApplyExternalTorque(b3SharedMemoryCommandHandle commandHandle, int bodyUniqueId, int linkId, const double torque[3], int flags);
+///experiments of robots interacting with non-rigid objects (such as btSoftBody)
b3SharedMemoryCommandHandle b3LoadBunnyCommandInit(b3PhysicsClientHandle physClient);
+int b3LoadBunnySetScale(b3SharedMemoryCommandHandle commandHandle, double scale);
+int b3LoadBunnySetMass(b3SharedMemoryCommandHandle commandHandle, double mass);
+int b3LoadBunnySetCollisionMargin(b3SharedMemoryCommandHandle commandHandle, double collisionMargin);
#ifdef __cplusplus
}
diff --git a/examples/SharedMemory/PhysicsClientExample.cpp b/examples/SharedMemory/PhysicsClientExample.cpp
index b0fe2be97..98c59b2d5 100644
--- a/examples/SharedMemory/PhysicsClientExample.cpp
+++ b/examples/SharedMemory/PhysicsClientExample.cpp
@@ -89,10 +89,10 @@ protected:
virtual void resetCamera()
{
- float dist = 4;
- float pitch = 193;
- float yaw = 25;
- float targetPos[3]={0,0,0.5};//-3,2.8,-2.5};
+ float dist = 4;
+ float pitch = 193;
+ float yaw = 25;
+ float targetPos[3]={0,0,0.5};//-3,2.8,-2.5};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
@@ -481,6 +481,22 @@ void PhysicsClientExample::prepareAndSubmitCommand(int commandId)
}
break;
}
+ case CMD_SET_SHADOW:
+ {
+ b3SharedMemoryCommandHandle commandHandle = b3InitRequestCameraImage(m_physicsClientHandle);
+ float viewMatrix[16];
+ float projectionMatrix[16];
+ m_guiHelper->getRenderInterface()->getActiveCamera()->getCameraProjectionMatrix(projectionMatrix);
+ m_guiHelper->getRenderInterface()->getActiveCamera()->getCameraViewMatrix(viewMatrix);
+
+ b3RequestCameraImageSetCameraMatrices(commandHandle, viewMatrix,projectionMatrix);
+ b3RequestCameraImageSetPixelResolution(commandHandle, camVisualizerWidth,camVisualizerHeight);
+ bool hasShadow = true;
+ b3RequestCameraImageSetShadow(commandHandle, hasShadow);
+ b3SubmitClientCommand(m_physicsClientHandle, commandHandle);
+ break;
+ }
+
default:
{
b3Error("Unknown buttonId");
@@ -556,6 +572,7 @@ void PhysicsClientExample::createButtons()
createButton("Load URDF",CMD_LOAD_URDF, isTrigger);
createButton("Load SDF",CMD_LOAD_SDF, isTrigger);
createButton("Save World",CMD_SAVE_WORLD, isTrigger);
+ createButton("Set Shadow",CMD_SET_SHADOW, isTrigger);
createButton("Get Camera Image",CMD_REQUEST_CAMERA_IMAGE_DATA,isTrigger);
createButton("Step Sim",CMD_STEP_FORWARD_SIMULATION, isTrigger);
createButton("Realtime Sim",CMD_CUSTOM_SET_REALTIME_SIMULATION, isTrigger);
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.cpp b/examples/SharedMemory/PhysicsClientSharedMemory.cpp
index 334806ff5..e02d11e2d 100644
--- a/examples/SharedMemory/PhysicsClientSharedMemory.cpp
+++ b/examples/SharedMemory/PhysicsClientSharedMemory.cpp
@@ -40,7 +40,7 @@ struct PhysicsClientSharedMemoryInternalData {
btAlignedObjectArray m_cachedSegmentationMaskBuffer;
btAlignedObjectArray m_cachedContactPoints;
-
+ btAlignedObjectArray m_cachedOverlappingObjects;
btAlignedObjectArray m_cachedVisualShapes;
btAlignedObjectArray m_bodyIdsRequestInfo;
@@ -100,6 +100,10 @@ bool PhysicsClientSharedMemory::getBodyInfo(int bodyUniqueId, struct b3BodyInfo&
info.m_baseName = bodyJoints->m_baseName.c_str();
return true;
}
+
+
+
+
return false;
}
@@ -124,8 +128,11 @@ bool PhysicsClientSharedMemory::getJointInfo(int bodyUniqueId, int jointIndex, b
if (bodyJointsPtr && *bodyJointsPtr)
{
BodyJointInfoCache* bodyJoints = *bodyJointsPtr;
- info = bodyJoints->m_jointInfo[jointIndex];
- return true;
+ if ((jointIndex >= 0) && (jointIndex < bodyJoints->m_jointInfo.size()))
+ {
+ info = bodyJoints->m_jointInfo[jointIndex];
+ return true;
+ }
}
return false;
}
@@ -201,6 +208,32 @@ bool PhysicsClientSharedMemory::connect() {
b3Error("Cannot connect to shared memory");
return false;
}
+#if 0
+ if (m_data->m_isConnected)
+ {
+ //get all existing bodies and body info...
+
+ SharedMemoryCommand& command = m_data->m_testBlock1->m_clientCommands[0];
+ //now transfer the information of the individual objects etc.
+ command.m_type = CMD_REQUEST_BODY_INFO;
+ command.m_sdfRequestInfoArgs.m_bodyUniqueId = 37;
+ submitClientCommand(command);
+ int timeout = 1024 * 1024 * 1024;
+
+ const SharedMemoryStatus* status = 0;
+
+ while ((status == 0) && (timeout-- > 0))
+ {
+ status = processServerStatus();
+
+ }
+
+
+ //submitClientCommand(command);
+
+
+ }
+#endif
return true;
}
@@ -210,7 +243,7 @@ void PhysicsClientSharedMemory::processBodyJointInfo(int bodyUniqueId, const Sha
{
bParse::btBulletFile bf(
&this->m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor[0],
- serverCmd.m_dataStreamArguments.m_streamChunkLength);
+ serverCmd.m_numDataStreamBytes);
bf.setFileDNAisMemoryDNA();
bf.parse(false);
@@ -291,16 +324,17 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() {
break;
}
+
case CMD_URDF_LOADING_COMPLETED: {
if (m_data->m_verboseOutput) {
b3Printf("Server loading the URDF OK\n");
}
- if (serverCmd.m_dataStreamArguments.m_streamChunkLength > 0) {
+ if (serverCmd.m_numDataStreamBytes > 0) {
bParse::btBulletFile bf(
this->m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor,
- serverCmd.m_dataStreamArguments.m_streamChunkLength);
+ serverCmd.m_numDataStreamBytes);
bf.setFileDNAisMemoryDNA();
bf.parse(false);
int bodyUniqueId = serverCmd.m_dataStreamArguments.m_bodyUniqueId;
@@ -592,6 +626,30 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() {
b3Warning("Inverse Dynamics computations failed");
break;
}
+ case CMD_REQUEST_AABB_OVERLAP_FAILED:
+ {
+ b3Warning("Overlapping object query failed");
+ break;
+ }
+ case CMD_REQUEST_AABB_OVERLAP_COMPLETED:
+ {
+ if (m_data->m_verboseOutput)
+ {
+ b3Printf("Overlapping object request completed");
+ }
+
+ int startOverlapIndex = serverCmd.m_sendOverlappingObjectsArgs.m_startingOverlappingObjectIndex;
+ int numOverlapCopied = serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied;
+ m_data->m_cachedOverlappingObjects.resize(startOverlapIndex + numOverlapCopied);
+ b3OverlappingObject* objects = (b3OverlappingObject*)m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor;
+
+ for (int i = 0; i < numOverlapCopied; i++)
+ {
+ m_data->m_cachedOverlappingObjects[startOverlapIndex + i] = objects[i];
+ }
+
+ break;
+ }
case CMD_CONTACT_POINT_INFORMATION_COMPLETED:
{
if (m_data->m_verboseOutput)
@@ -675,6 +733,43 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() {
b3Warning("Load texture failed");
break;
}
+ case CMD_BULLET_LOADING_COMPLETED:
+ {
+ break;
+ }
+ case CMD_BULLET_LOADING_FAILED:
+ {
+ b3Warning("Load .bullet failed");
+ break;
+ }
+ case CMD_BULLET_SAVING_FAILED:
+ {
+ b3Warning("Save .bullet failed");
+ break;
+ }
+ case CMD_MJCF_LOADING_FAILED:
+ {
+ b3Warning("Load .mjcf failed");
+ break;
+ }
+ case CMD_USER_DEBUG_DRAW_COMPLETED:
+ {
+ break;
+ }
+ case CMD_USER_DEBUG_DRAW_FAILED:
+ {
+ b3Warning("User debug draw failed");
+ break;
+ }
+ case CMD_USER_CONSTRAINT_COMPLETED:
+ {
+ break;
+ }
+ case CMD_USER_CONSTRAINT_FAILED:
+ {
+ b3Warning("createConstraint failed");
+ break;
+ }
default: {
b3Error("Unknown server status %d\n", serverCmd.m_type);
btAssert(0);
@@ -736,6 +831,18 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() {
m_data->m_lastServerStatus = m_data->m_tempBackupServerStatus;
}
}
+
+ if (serverCmd.m_type == CMD_REQUEST_AABB_OVERLAP_COMPLETED)
+ {
+ SharedMemoryCommand& command = m_data->m_testBlock1->m_clientCommands[0];
+ if (serverCmd.m_sendOverlappingObjectsArgs.m_numRemainingOverlappingObjects > 0 && serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied)
+ {
+ command.m_type = CMD_REQUEST_AABB_OVERLAP;
+ command.m_requestOverlappingObjectsArgs.m_startingOverlappingObjectIndex = serverCmd.m_sendOverlappingObjectsArgs.m_startingOverlappingObjectIndex + serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied;
+ submitClientCommand(command);
+ return 0;
+ }
+ }
if (serverCmd.m_type == CMD_CONTACT_POINT_INFORMATION_COMPLETED)
{
@@ -869,6 +976,14 @@ void PhysicsClientSharedMemory::getCachedContactPointInformation(struct b3Contac
}
+void PhysicsClientSharedMemory::getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects)
+{
+ overlappingObjects->m_numOverlappingObjects = m_data->m_cachedOverlappingObjects.size();
+ overlappingObjects->m_overlappingObjects = m_data->m_cachedOverlappingObjects.size() ?
+ &m_data->m_cachedOverlappingObjects[0] : 0;
+}
+
+
void PhysicsClientSharedMemory::getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo)
{
visualShapesInfo->m_numVisualShapes = m_data->m_cachedVisualShapes.size();
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.h b/examples/SharedMemory/PhysicsClientSharedMemory.h
index 2dc659646..d5f6b3cff 100644
--- a/examples/SharedMemory/PhysicsClientSharedMemory.h
+++ b/examples/SharedMemory/PhysicsClientSharedMemory.h
@@ -12,7 +12,7 @@ class PhysicsClientSharedMemory : public PhysicsClient {
protected:
virtual void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem);
void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd);
-
+
public:
PhysicsClientSharedMemory();
@@ -57,6 +57,8 @@ public:
virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData);
+ virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects);
+
virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo);
};
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2.cpp b/examples/SharedMemory/PhysicsClientSharedMemory2.cpp
new file mode 100644
index 000000000..7eea2298d
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory2.cpp
@@ -0,0 +1,27 @@
+
+#include "PhysicsClientSharedMemory2.h"
+#include "PosixSharedMemory.h"
+#include "Win32SharedMemory.h"
+#include "Bullet3Common/b3Logging.h"
+#include "Bullet3Common/b3Scalar.h"
+
+#include "SharedMemoryCommandProcessor.h"
+
+
+PhysicsClientSharedMemory2::PhysicsClientSharedMemory2(SharedMemoryCommandProcessor* proc)
+ :PhysicsDirect(proc)
+{
+ m_proc = proc;
+}
+PhysicsClientSharedMemory2::~PhysicsClientSharedMemory2()
+{
+}
+
+void PhysicsClientSharedMemory2::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem)
+{
+ if (m_proc)
+ {
+ m_proc->setSharedMemoryInterface(sharedMem);
+ }
+}
+
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2.h b/examples/SharedMemory/PhysicsClientSharedMemory2.h
new file mode 100644
index 000000000..e3b109370
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory2.h
@@ -0,0 +1,18 @@
+#ifndef PHYSICS_CLIENT_SHARED_MEMORY2_H
+#define PHYSICS_CLIENT_SHARED_MEMORY2_H
+
+#include "PhysicsDirect.h"
+
+class PhysicsClientSharedMemory2 : public PhysicsDirect
+{
+ class SharedMemoryCommandProcessor* m_proc;
+
+public:
+ PhysicsClientSharedMemory2(SharedMemoryCommandProcessor* proc);
+ virtual ~PhysicsClientSharedMemory2();
+
+ void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem);
+
+};
+
+#endif //PHYSICS_CLIENT_SHARED_MEMORY2_H
\ No newline at end of file
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp
new file mode 100644
index 000000000..7323205d0
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp
@@ -0,0 +1,19 @@
+#include "PhysicsClientSharedMemory2_C_API.h"
+
+#include "PhysicsDirect.h"
+#include "SharedMemoryCommandProcessor.h"
+
+b3PhysicsClientHandle b3ConnectSharedMemory2(int key)
+{
+
+ SharedMemoryCommandProcessor* cmdProc = new SharedMemoryCommandProcessor();
+ cmdProc->setSharedMemoryKey(key);
+ PhysicsDirect* cl = new PhysicsDirect(cmdProc);
+
+ cl->setSharedMemoryKey(key);
+
+ cl->connect();
+
+ return (b3PhysicsClientHandle)cl;
+}
+
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h
new file mode 100644
index 000000000..95d4bf690
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h
@@ -0,0 +1,18 @@
+#ifndef PHYSICS_CLIENT_SHARED_MEMORY2_H
+#define PHYSICS_CLIENT_SHARED_MEMORY2_H
+
+#include "PhysicsClientC_API.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+b3PhysicsClientHandle b3ConnectSharedMemory2(int key);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PHYSICS_CLIENT_SHARED_MEMORY2_H
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp
new file mode 100644
index 000000000..36c794f80
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp
@@ -0,0 +1,11 @@
+#include "PhysicsClientSharedMemory_C_API.h"
+
+#include "PhysicsClientSharedMemory.h"
+
+b3PhysicsClientHandle b3ConnectSharedMemory(int key)
+{
+ PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory();
+ cl->setSharedMemoryKey(key);
+ cl->connect();
+ return (b3PhysicsClientHandle)cl;
+}
diff --git a/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h
new file mode 100644
index 000000000..2a4e4e665
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h
@@ -0,0 +1,16 @@
+#ifndef PHYSICS_CLIENT_SHARED_MEMORY_H
+#define PHYSICS_CLIENT_SHARED_MEMORY_H
+
+#include "PhysicsClientC_API.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ b3PhysicsClientHandle b3ConnectSharedMemory(int key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PHYSICS_CLIENT_SHARED_MEMORY_H
diff --git a/examples/SharedMemory/PhysicsClientUDP.cpp b/examples/SharedMemory/PhysicsClientUDP.cpp
new file mode 100644
index 000000000..0d76f8310
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientUDP.cpp
@@ -0,0 +1,592 @@
+#include "PhysicsClientUDP.h"
+#include
+#include
+#include
+#include "../Utils/b3Clock.h"
+#include "PhysicsClient.h"
+//#include "LinearMath/btVector3.h"
+#include "SharedMemoryCommands.h"
+#include
+#include "Bullet3Common/b3Logging.h"
+#include "../MultiThreading/b3ThreadSupportInterface.h"
+void UDPThreadFunc(void* userPtr, void* lsMemory);
+void* UDPlsMemoryFunc();
+bool gVerboseNetworkMessagesClient = false;
+
+#ifndef _WIN32
+#include "../MultiThreading/b3PosixThreadSupport.h"
+
+b3ThreadSupportInterface* createUDPThreadSupport(int numThreads)
+{
+ b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("UDPThread",
+ UDPThreadFunc,
+ UDPlsMemoryFunc,
+ numThreads);
+ b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo);
+
+ return threadSupport;
+
+}
+
+
+#elif defined( _WIN32)
+#include "../MultiThreading/b3Win32ThreadSupport.h"
+
+b3ThreadSupportInterface* createUDPThreadSupport(int numThreads)
+{
+ b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("UDPThread", UDPThreadFunc, UDPlsMemoryFunc, numThreads);
+ b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo);
+ return threadSupport;
+
+}
+#endif
+
+
+
+struct UDPThreadLocalStorage
+{
+ int threadId;
+};
+
+
+
+unsigned int b3DeserializeInt(const unsigned char* input)
+{
+ unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0];
+ return tmp;
+}
+
+struct UdpNetworkedInternalData
+{
+ ENetHost* m_client;
+ ENetAddress m_address;
+ ENetPeer* m_peer;
+ ENetEvent m_event;
+ bool m_isConnected;
+
+ b3ThreadSupportInterface* m_threadSupport;
+
+ b3CriticalSection* m_cs;
+
+ UdpNetworkedInternalData* m_udpInternalData;
+
+
+ SharedMemoryCommand m_clientCmd;
+ bool m_hasCommand;
+
+ bool m_hasStatus;
+ SharedMemoryStatus m_lastStatus;
+ b3AlignedObjectArray m_stream;
+
+ std::string m_hostName;
+ int m_port;
+
+ UdpNetworkedInternalData()
+ :m_client(0),
+ m_peer(0),
+ m_isConnected(false),
+ m_threadSupport(0),
+ m_hasCommand(false),
+ m_hasStatus(false)
+ {
+
+ }
+
+ bool connectUDP()
+ {
+ if (m_isConnected)
+ return true;
+
+
+
+ if (enet_initialize() != 0)
+ {
+ fprintf(stderr, "Error initialising enet");
+
+ exit(EXIT_FAILURE);
+
+ }
+
+ m_client = enet_host_create(NULL, /* create a client host */
+ 1, /* number of clients */
+ 2, /* number of channels */
+ 57600 / 8, /* incoming bandwith */
+ 14400 / 8); /* outgoing bandwith */
+
+ if (m_client == NULL) {
+ fprintf(stderr, "Could not create client host");
+ return false;
+ }
+
+ enet_address_set_host(&m_address, m_hostName.c_str());
+ m_address.port = m_port;
+
+ m_peer = enet_host_connect(m_client,
+ &m_address, /* address to connect to */
+ 2, /* number of channels */
+ 0); /* user data supplied to
+ the receiving host */
+
+ if (m_peer == NULL) {
+ fprintf(stderr, "No available peers for initiating an ENet "
+ "connection.\n");
+ return false;
+
+ }
+
+
+ /* Try to connect to server within 5 seconds */
+ if (enet_host_service(m_client, &m_event, 5000) > 0 &&
+ m_event.type == ENET_EVENT_TYPE_CONNECT)
+ {
+ puts("Connection to server succeeded.");
+ }
+ else
+ {
+ /* Either the 5 seconds are up or a disconnect event was */
+ /* received. Reset the peer in the event the 5 seconds */
+ /* had run out without any significant event. */
+ enet_peer_reset(m_peer);
+
+ fprintf(stderr, "Connection to server failed.");
+ return false;
+ }
+
+
+ int serviceResult = enet_host_service(m_client, &m_event, 0);
+
+ if (serviceResult > 0)
+ {
+ switch (m_event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ printf("A new client connected from %x:%u.\n",
+ m_event.peer->address.host,
+ m_event.peer->address.port);
+ m_event.peer->data = (void*)"New User";
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+
+ if (gVerboseNetworkMessagesClient)
+ {
+ printf("A packet of length %u containing '%s' was "
+ "received from %s on channel %u.\n",
+ m_event.packet->dataLength,
+ m_event.packet->data,
+ m_event.peer->data,
+ m_event.channelID);
+ }
+ /* Clean up the packet now that we're done using it.
+ > */
+ enet_packet_destroy(m_event.packet);
+
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ printf("%s disconected.\n", m_event.peer->data);
+
+ break;
+ default:
+ {
+ printf("unknown event type: %d.\n", m_event.type);
+ }
+ }
+ }
+ else if (serviceResult > 0)
+ {
+ puts("Error with servicing the client");
+ return false;
+ }
+
+ m_isConnected = true;
+ return m_isConnected;
+ }
+
+ bool checkData()
+ {
+ bool hasStatus = false;
+
+ int serviceResult = enet_host_service(m_client, &m_event, 0);
+
+ if (serviceResult > 0)
+ {
+ switch (m_event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ printf("A new client connected from %x:%u.\n",
+ m_event.peer->address.host,
+ m_event.peer->address.port);
+
+ m_event.peer->data = (void*)"New User";
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ {
+ if (gVerboseNetworkMessagesClient)
+ {
+ printf("A packet of length %u containing '%s' was "
+ "received from %s on channel %u.\n",
+ m_event.packet->dataLength,
+ m_event.packet->data,
+ m_event.peer->data,
+ m_event.channelID);
+ }
+
+ int packetSizeInBytes = b3DeserializeInt(m_event.packet->data);
+
+ if (packetSizeInBytes == m_event.packet->dataLength)
+ {
+
+ SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&m_event.packet->data[4];
+ m_lastStatus = *statPtr;
+ int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus);
+ int numStreamBytes = packetSizeInBytes - streamOffsetInBytes;
+ m_stream.resize(numStreamBytes);
+ for (int i = 0; i < numStreamBytes; i++)
+ {
+ m_stream[i] = m_event.packet->data[i + streamOffsetInBytes];
+ }
+ }
+ else
+ {
+ printf("unknown status message received\n");
+ }
+ enet_packet_destroy(m_event.packet);
+ hasStatus = true;
+ break;
+ }
+ case ENET_EVENT_TYPE_DISCONNECT:
+ {
+ printf("%s disconected.\n", m_event.peer->data);
+
+ break;
+ }
+ default:
+ {
+ printf("unknown event type: %d.\n", m_event.type);
+ }
+ }
+ }
+ else if (serviceResult > 0)
+ {
+ puts("Error with servicing the client");
+ }
+
+ return hasStatus;
+ }
+
+};
+
+enum UDPThreadEnums
+{
+ eUDPRequestTerminate = 13,
+ eUDPIsUnInitialized,
+ eUDPIsInitialized,
+ eUDPInitializationFailed,
+ eUDPHasTerminated
+};
+
+
+
+enum UDPCommandEnums
+{
+ eUDPIdle = 13,
+ eUDP_ConnectRequest,
+ eUDP_Connected,
+ eUDP_ConnectionFailed,
+ eUDP_DisconnectRequest,
+ eUDP_Disconnected,
+
+};
+
+void UDPThreadFunc(void* userPtr, void* lsMemory)
+{
+ printf("UDPThreadFunc thread started\n");
+ UDPThreadLocalStorage* localStorage = (UDPThreadLocalStorage*)lsMemory;
+
+ UdpNetworkedInternalData* args = (UdpNetworkedInternalData*)userPtr;
+ int workLeft = true;
+ b3Clock clock;
+ clock.reset();
+ bool init = true;
+ if (init)
+ {
+
+ args->m_cs->lock();
+ args->m_cs->setSharedParam(0, eUDPIsInitialized);
+ args->m_cs->unlock();
+
+
+ double deltaTimeInSeconds = 0;
+
+ do
+ {
+ deltaTimeInSeconds += double(clock.getTimeMicroseconds()) / 1000000.;
+
+ if (deltaTimeInSeconds<(1. / 5000.))
+ {
+// b3Clock::usleep(250);
+ }
+ else
+ {
+
+ clock.reset();
+ deltaTimeInSeconds = 0.f;
+ switch (args->m_cs->getSharedParam(1))
+ {
+ case eUDP_ConnectRequest:
+ {
+ bool connected = args->connectUDP();
+ if (connected)
+ {
+ args->m_cs->setSharedParam(1, eUDP_Connected);
+ }
+ else
+ {
+ args->m_cs->setSharedParam(1, eUDP_ConnectionFailed);
+ }
+ break;
+ }
+ default:
+ {
+ }
+ };
+
+ if (args->m_isConnected)
+ {
+
+ args->m_cs->lock();
+ bool hasCommand = args->m_hasCommand;
+ args->m_cs->unlock();
+
+
+ if (hasCommand)
+ {
+
+ int sz = sizeof(SharedMemoryCommand);
+ ENetPacket *packet = enet_packet_create(&args->m_clientCmd, sz, ENET_PACKET_FLAG_RELIABLE);
+ int res = enet_peer_send(args->m_peer, 0, packet);
+ args->m_cs->lock();
+ args->m_hasCommand = false;
+ args->m_cs->unlock();
+ }
+
+
+ bool hasNewStatus = args->checkData();
+ if (hasNewStatus)
+ {
+ if (args->m_hasStatus)
+ {
+ //overflow: last status hasn't been processed yet
+ b3Assert(0);
+ printf("Error: received new status but previous status not processed yet");
+ }
+ else
+ {
+ args->m_cs->lock();
+ args->m_hasStatus = hasNewStatus;
+ args->m_cs->unlock();
+ }
+ }
+ }
+
+ }
+
+ } while (args->m_cs->getSharedParam(0) != eUDPRequestTerminate);
+ }
+ else
+ {
+ args->m_cs->lock();
+ args->m_cs->setSharedParam(0, eUDPInitializationFailed);
+ args->m_cs->unlock();
+ }
+
+
+ printf("finished\n");
+
+}
+
+
+
+void* UDPlsMemoryFunc()
+{
+ //don't create local store memory, just return 0
+ return new UDPThreadLocalStorage;
+}
+
+
+
+
+
+
+
+UdpNetworkedPhysicsProcessor::UdpNetworkedPhysicsProcessor(const char* hostName, int port)
+{
+ m_data = new UdpNetworkedInternalData;
+ if (hostName)
+ {
+ m_data->m_hostName = hostName;
+ }
+ m_data->m_port = port;
+
+}
+
+UdpNetworkedPhysicsProcessor::~UdpNetworkedPhysicsProcessor()
+{
+ disconnect();
+ delete m_data;
+}
+
+bool UdpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
+{
+ int sz = sizeof(SharedMemoryCommand);
+ int timeout = 1024 * 1024 * 1024;
+
+ m_data->m_cs->lock();
+ m_data->m_clientCmd = clientCmd;
+ m_data->m_hasCommand = true;
+ m_data->m_cs->unlock();
+
+ while (m_data->m_hasCommand && (timeout-- > 0))
+ {
+// b3Clock::usleep(100);
+ }
+
+#if 0
+
+ timeout = 1024 * 1024 * 1024;
+
+ bool hasStatus = false;
+
+ const SharedMemoryStatus* stat = 0;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ hasStatus = receiveStatus(serverStatusOut, bufferServerToClient, bufferSizeInBytes);
+ b3Clock::usleep(100);
+ }
+ return hasStatus;
+
+#endif
+
+ return false;
+}
+
+bool UdpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
+{
+ bool hasStatus = false;
+ if (m_data->m_hasStatus)
+ {
+ hasStatus = true;
+ serverStatusOut = m_data->m_lastStatus;
+ int numStreamBytes = m_data->m_stream.size();
+
+ if (numStreamBytes < bufferSizeInBytes)
+ {
+ for (int i = 0; i < numStreamBytes; i++)
+ {
+ bufferServerToClient[i] = m_data->m_stream[i];
+ }
+ }
+ else
+ {
+ printf("Error: steam buffer overflow\n");
+ }
+
+ m_data->m_cs->lock();
+ m_data->m_hasStatus = false;
+ m_data->m_cs->unlock();
+ }
+
+
+ return hasStatus;
+
+}
+
+
+void UdpNetworkedPhysicsProcessor::renderScene()
+{
+}
+
+void UdpNetworkedPhysicsProcessor::physicsDebugDraw(int debugDrawFlags)
+{
+}
+
+void UdpNetworkedPhysicsProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper)
+{
+}
+
+bool UdpNetworkedPhysicsProcessor::isConnected() const
+{
+ return m_data->m_isConnected;
+}
+
+
+bool UdpNetworkedPhysicsProcessor::connect()
+{
+ if (m_data->m_threadSupport==0)
+ {
+ m_data->m_threadSupport = createUDPThreadSupport(1);
+
+ m_data->m_cs = m_data->m_threadSupport->createCriticalSection();
+ m_data->m_cs->setSharedParam(0, eUDPIsUnInitialized);
+ m_data->m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*) m_data, 0);
+
+ while (m_data->m_cs->getSharedParam(0) == eUDPIsUnInitialized)
+ {
+ b3Clock::usleep(1000);
+ }
+
+ m_data->m_cs->lock();
+ m_data->m_cs->setSharedParam(1, eUDP_ConnectRequest);
+ m_data->m_cs->unlock();
+
+ while (m_data->m_cs->getSharedParam(1) == eUDP_ConnectRequest)
+ {
+ b3Clock::usleep(1000);
+ }
+
+ }
+
+
+ return true;
+}
+
+void UdpNetworkedPhysicsProcessor::disconnect()
+{
+ if (m_data->m_threadSupport)
+ {
+ m_data->m_cs->lock();
+ m_data->m_cs->setSharedParam(0, eUDPRequestTerminate);
+ m_data->m_cs->unlock();
+
+ int numActiveThreads = 1;
+
+ while (numActiveThreads)
+ {
+ int arg0, arg1;
+ if (m_data->m_threadSupport->isTaskCompleted(&arg0, &arg1, 0))
+ {
+ numActiveThreads--;
+ printf("numActiveThreads = %d\n", numActiveThreads);
+ }
+ else
+ {
+ b3Clock::usleep(1000);
+ }
+ };
+
+ printf("stopping threads\n");
+
+ delete m_data->m_threadSupport;
+ m_data->m_threadSupport = 0;
+ }
+
+
+
+}
+
+
+
+
+
diff --git a/examples/SharedMemory/PhysicsClientUDP.h b/examples/SharedMemory/PhysicsClientUDP.h
new file mode 100644
index 000000000..27b94fd48
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientUDP.h
@@ -0,0 +1,37 @@
+#ifndef PHYSICS_CLIENT_UDP_H
+#define PHYSICS_CLIENT_UDP_H
+
+#include "PhysicsDirect.h"
+#include "PhysicsServerCommandProcessor.h"
+
+class UdpNetworkedPhysicsProcessor : public PhysicsCommandProcessorInterface
+{
+
+ struct UdpNetworkedInternalData* m_data;
+
+public:
+ UdpNetworkedPhysicsProcessor(const char* hostName, int port);
+
+ virtual ~UdpNetworkedPhysicsProcessor();
+
+ virtual bool connect();
+
+ virtual void disconnect();
+
+ virtual bool isConnected() const;
+
+ virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
+
+ virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
+
+ virtual void renderScene();
+
+ virtual void physicsDebugDraw(int debugDrawFlags);
+
+ virtual void setGuiHelper(struct GUIHelperInterface* guiHelper);
+
+};
+
+
+#endif //PHYSICS_CLIENT_UDP_H
+
diff --git a/examples/SharedMemory/PhysicsClientUDP_C_API.cpp b/examples/SharedMemory/PhysicsClientUDP_C_API.cpp
new file mode 100644
index 000000000..f48fdedb8
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientUDP_C_API.cpp
@@ -0,0 +1,21 @@
+
+#include "PhysicsClientUDP_C_API.h"
+#include "PhysicsClientUDP.h"
+#include "PhysicsDirect.h"
+#include
+
+//think more about naming. The b3ConnectPhysicsLoopback
+b3PhysicsClientHandle b3ConnectPhysicsUDP(const char* hostName, int port)
+{
+
+ UdpNetworkedPhysicsProcessor* udp = new UdpNetworkedPhysicsProcessor(hostName, port);
+
+ PhysicsDirect* direct = new PhysicsDirect(udp);
+
+ bool connected = direct->connect();
+ printf("direct!\n");
+ return (b3PhysicsClientHandle)direct;
+}
+
+
+
diff --git a/examples/SharedMemory/PhysicsClientUDP_C_API.h b/examples/SharedMemory/PhysicsClientUDP_C_API.h
new file mode 100644
index 000000000..fdb97bcab
--- /dev/null
+++ b/examples/SharedMemory/PhysicsClientUDP_C_API.h
@@ -0,0 +1,19 @@
+#ifndef PHYSICS_CLIENT_UDP_C_API_H
+#define PHYSICS_CLIENT_UDP_C_API_H
+
+#include "PhysicsClientC_API.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+ ///send physics commands using UDP networking
+ b3PhysicsClientHandle b3ConnectPhysicsUDP(const char* hostName, int port);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PHYSICS_CLIENT_UDP_C_API_H
diff --git a/examples/SharedMemory/PhysicsCommandProcessorInterface.h b/examples/SharedMemory/PhysicsCommandProcessorInterface.h
new file mode 100644
index 000000000..39b5f36d5
--- /dev/null
+++ b/examples/SharedMemory/PhysicsCommandProcessorInterface.h
@@ -0,0 +1,27 @@
+#ifndef PHYSICS_COMMAND_PROCESSOR_INTERFACE_H
+#define PHYSICS_COMMAND_PROCESSOR_INTERFACE_H
+
+class PhysicsCommandProcessorInterface
+{
+
+public:
+ virtual ~PhysicsCommandProcessorInterface() {}
+
+ virtual bool connect()=0;
+
+ virtual void disconnect() = 0;
+
+ virtual bool isConnected() const = 0;
+
+ virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0;
+
+ virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0;
+
+ virtual void renderScene() = 0;
+ virtual void physicsDebugDraw(int debugDrawFlags) = 0;
+ virtual void setGuiHelper(struct GUIHelperInterface* guiHelper) = 0;
+
+
+};
+
+#endif //PHYSICS_COMMAND_PROCESSOR_INTERFACE_H
diff --git a/examples/SharedMemory/PhysicsDirect.cpp b/examples/SharedMemory/PhysicsDirect.cpp
index 65c1beb13..cb7a16abd 100644
--- a/examples/SharedMemory/PhysicsDirect.cpp
+++ b/examples/SharedMemory/PhysicsDirect.cpp
@@ -3,7 +3,9 @@
#include "PhysicsClientSharedMemory.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "SharedMemoryCommands.h"
-#include "PhysicsServerCommandProcessor.h"
+#include "PhysicsCommandProcessorInterface.h"
+
+
#include "LinearMath/btHashMap.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../../Extras/Serialize/BulletFileLoader/btBulletFile.h"
@@ -21,6 +23,7 @@ struct PhysicsDirectInternalData
{
DummyGUIHelper m_noGfx;
+ btAlignedObjectArray m_serverDNA;
SharedMemoryCommand m_command;
SharedMemoryStatus m_serverStatus;
bool m_hasStatus;
@@ -41,29 +44,38 @@ struct PhysicsDirectInternalData
btAlignedObjectArray m_cachedSegmentationMask;
btAlignedObjectArray m_cachedContactPoints;
-
+ btAlignedObjectArray m_cachedOverlappingObjects;
+
btAlignedObjectArray m_cachedVisualShapes;
- PhysicsServerCommandProcessor* m_commandProcessor;
+ PhysicsCommandProcessorInterface* m_commandProcessor;
+ bool m_ownsCommandProcessor;
PhysicsDirectInternalData()
:m_hasStatus(false),
- m_verboseOutput(false)
+ m_verboseOutput(false),
+ m_ownsCommandProcessor(false)
{
}
};
-PhysicsDirect::PhysicsDirect()
+PhysicsDirect::PhysicsDirect(PhysicsCommandProcessorInterface* physSdk)
{
m_data = new PhysicsDirectInternalData;
- m_data->m_commandProcessor = new PhysicsServerCommandProcessor;
-
-
+ m_data->m_commandProcessor = physSdk;
+ m_data->m_ownsCommandProcessor = false;
}
PhysicsDirect::~PhysicsDirect()
{
- delete m_data->m_commandProcessor;
+ if (m_data->m_commandProcessor->isConnected())
+ {
+ m_data->m_commandProcessor->disconnect();
+ }
+ if (m_data->m_ownsCommandProcessor)
+ {
+ delete m_data->m_commandProcessor;
+ }
delete m_data;
}
@@ -71,23 +83,51 @@ PhysicsDirect::~PhysicsDirect()
// return true if connection succesfull, can also check 'isConnected'
bool PhysicsDirect::connect()
{
+ bool connected = m_data->m_commandProcessor->connect();
m_data->m_commandProcessor->setGuiHelper(&m_data->m_noGfx);
- return true;
+
+ //also request serialization data
+ {
+ SharedMemoryCommand command;
+ command.m_type = CMD_REQUEST_INTERNAL_DATA;
+ bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+ if (hasStatus)
+ {
+ postProcessStatus(m_data->m_serverStatus);
+ }
+ else
+ {
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+ }
+ }
+
+ return connected;
}
// return true if connection succesfull, can also check 'isConnected'
bool PhysicsDirect::connect(struct GUIHelperInterface* guiHelper)
{
+ bool connected = m_data->m_commandProcessor->connect();
+
m_data->m_commandProcessor->setGuiHelper(guiHelper);
- return true;
+ return connected;
}
void PhysicsDirect::renderScene()
{
m_data->m_commandProcessor->renderScene();
}
+
void PhysicsDirect::debugDraw(int debugDrawMode)
{
m_data->m_commandProcessor->physicsDebugDraw(debugDrawMode);
@@ -96,21 +136,31 @@ void PhysicsDirect::debugDraw(int debugDrawMode)
////todo: rename to 'disconnect'
void PhysicsDirect::disconnectSharedMemory()
{
+ m_data->m_commandProcessor->disconnect();
m_data->m_commandProcessor->setGuiHelper(0);
}
bool PhysicsDirect::isConnected() const
{
- return true;
+ return m_data->m_commandProcessor->isConnected();
}
// return non-null if there is a status, nullptr otherwise
const SharedMemoryStatus* PhysicsDirect::processServerStatus()
{
+
+ if (!m_data->m_hasStatus)
+ {
+ m_data->m_hasStatus = m_data->m_commandProcessor->receiveStatus(m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+ }
+
SharedMemoryStatus* stat = 0;
if (m_data->m_hasStatus)
{
stat = &m_data->m_serverStatus;
+
+ postProcessStatus(m_data->m_serverStatus);
+
m_data->m_hasStatus = false;
}
return stat;
@@ -136,7 +186,19 @@ bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgComma
{
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+
m_data->m_hasStatus = hasStatus;
+
if (hasStatus)
{
btAssert(m_data->m_serverStatus.m_type == CMD_DEBUG_LINES_COMPLETED);
@@ -184,6 +246,8 @@ bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgComma
if (serverCmd.m_sendDebugLinesArgs.m_numRemainingDebugLines > 0)
{
+ m_data->m_hasStatus = false;
+
command.m_type = CMD_REQUEST_DEBUG_LINES;
command.m_requestDebugLinesArguments.m_startingLineIndex =
serverCmd.m_sendDebugLinesArgs.m_numDebugLines +
@@ -204,6 +268,17 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org
do
{
bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+
m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
@@ -223,6 +298,8 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org
if (serverCmd.m_sendVisualShapeArgs.m_numRemainingVisualShapes >0 && serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied)
{
+ m_data->m_hasStatus = false;
+
command.m_type = CMD_REQUEST_VISUAL_SHAPE_INFO;
command.m_requestVisualShapeDataArguments.m_startingVisualShapeIndex = serverCmd.m_sendVisualShapeArgs.m_startingVisualShapeIndex + serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied;
command.m_requestVisualShapeDataArguments.m_bodyUniqueId = serverCmd.m_sendVisualShapeArgs.m_bodyUniqueId;
@@ -233,6 +310,60 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org
return m_data->m_hasStatus;
}
+bool PhysicsDirect::processOverlappingObjects(const struct SharedMemoryCommand& orgCommand)
+{
+ SharedMemoryCommand command = orgCommand;
+
+ const SharedMemoryStatus& serverCmd = m_data->m_serverStatus;
+
+ do
+ {
+ bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+
+
+ m_data->m_hasStatus = hasStatus;
+ if (hasStatus)
+ {
+ if (m_data->m_verboseOutput)
+ {
+ b3Printf("Overlapping Objects Request OK\n");
+ }
+
+ int startOverlapIndex = serverCmd.m_sendOverlappingObjectsArgs.m_startingOverlappingObjectIndex;
+ int numOverlapCopied = serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied;
+ m_data->m_cachedOverlappingObjects.resize(startOverlapIndex + numOverlapCopied);
+ b3OverlappingObject* objects = (b3OverlappingObject*)&m_data->m_bulletStreamDataServerToClient[0];
+
+ for (int i = 0; i < numOverlapCopied; i++)
+ {
+ m_data->m_cachedOverlappingObjects[startOverlapIndex + i] = objects[i];
+ }
+
+ if (serverCmd.m_sendOverlappingObjectsArgs.m_numRemainingOverlappingObjects > 0 && serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied)
+ {
+ m_data->m_hasStatus = false;
+ command.m_type = CMD_REQUEST_AABB_OVERLAP;
+ command.m_requestOverlappingObjectsArgs.m_startingOverlappingObjectIndex = serverCmd.m_sendOverlappingObjectsArgs.m_startingOverlappingObjectIndex + serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied;
+ }
+
+ }
+ } while (serverCmd.m_sendOverlappingObjectsArgs.m_numRemainingOverlappingObjects > 0 && serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied);
+
+ return m_data->m_hasStatus;
+
+}
+
+
bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& orgCommand)
{
@@ -243,7 +374,19 @@ bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& or
do
{
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
- m_data->m_hasStatus = hasStatus;
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+
+
+ m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
if (m_data->m_verboseOutput)
@@ -264,7 +407,10 @@ bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& or
if (serverCmd.m_sendContactPointArgs.m_numRemainingContactPoints>0 && serverCmd.m_sendContactPointArgs.m_numContactPointsCopied)
{
- command.m_type = CMD_REQUEST_CONTACT_POINT_INFORMATION;
+
+ m_data->m_hasStatus = false;
+
+ command.m_type = CMD_REQUEST_CONTACT_POINT_INFORMATION;
command.m_requestContactPointArguments.m_startingContactPointIndex = serverCmd.m_sendContactPointArgs.m_startingContactPointIndex+serverCmd.m_sendContactPointArgs.m_numContactPointsCopied;
command.m_requestContactPointArguments.m_objectAIndexFilter = -1;
command.m_requestContactPointArguments.m_objectBIndexFilter = -1;
@@ -289,6 +435,18 @@ bool PhysicsDirect::processCamera(const struct SharedMemoryCommand& orgCommand)
{
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ const SharedMemoryStatus* stat = processServerStatus();
+ if (stat)
+ {
+ hasStatus = true;
+ }
+ }
+
+
m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
@@ -340,6 +498,7 @@ bool PhysicsDirect::processCamera(const struct SharedMemoryCommand& orgCommand)
if (serverCmd.m_sendPixelDataArguments.m_numRemainingPixels > 0 && serverCmd.m_sendPixelDataArguments.m_numPixelsCopied)
{
+ m_data->m_hasStatus = false;
// continue requesting remaining pixels
command.m_type = CMD_REQUEST_CAMERA_IMAGE_DATA;
@@ -365,8 +524,15 @@ void PhysicsDirect::processBodyJointInfo(int bodyUniqueId, const SharedMemorySta
{
bParse::btBulletFile bf(
&m_data->m_bulletStreamDataServerToClient[0],
- serverCmd.m_dataStreamArguments.m_streamChunkLength);
- bf.setFileDNAisMemoryDNA();
+ serverCmd.m_numDataStreamBytes);
+ if (m_data->m_serverDNA.size())
+ {
+ bf.setFileDNA(false, &m_data->m_serverDNA[0], m_data->m_serverDNA.size());
+ }
+ else
+ {
+ bf.setFileDNAisMemoryDNA();
+ }
bf.parse(false);
BodyJointInfoCache2* bodyJoints = new BodyJointInfoCache2;
@@ -379,19 +545,27 @@ void PhysicsDirect::processBodyJointInfo(int bodyUniqueId, const SharedMemorySta
{
Bullet::btMultiBodyDoubleData* mb =
(Bullet::btMultiBodyDoubleData*)bf.m_multiBodies[i];
- bodyJoints->m_baseName = mb->m_baseName;
-
+
+ if (mb->m_baseName)
+ {
+ bodyJoints->m_baseName = mb->m_baseName;
+ }
addJointInfoFromMultiBodyData(mb,bodyJoints, m_data->m_verboseOutput);
} else
{
Bullet::btMultiBodyFloatData* mb =
(Bullet::btMultiBodyFloatData*)bf.m_multiBodies[i];
- bodyJoints->m_baseName = mb->m_baseName;
+
+ if (mb->m_baseName)
+ {
+ bodyJoints->m_baseName = mb->m_baseName;
+ }
addJointInfoFromMultiBodyData(mb,bodyJoints, m_data->m_verboseOutput);
}
}
- if (bf.ok()) {
+ if (bf.ok())
+ {
if (m_data->m_verboseOutput)
{
b3Printf("Received robot description ok!\n");
@@ -402,6 +576,118 @@ void PhysicsDirect::processBodyJointInfo(int bodyUniqueId, const SharedMemorySta
}
}
+void PhysicsDirect::postProcessStatus(const struct SharedMemoryStatus& serverCmd)
+{
+ switch (serverCmd.m_type)
+ {
+
+ case CMD_REQUEST_INTERNAL_DATA_COMPLETED:
+ {
+ if (serverCmd.m_numDataStreamBytes)
+ {
+ int numStreamBytes = serverCmd.m_numDataStreamBytes;
+ m_data->m_serverDNA.resize(numStreamBytes);
+ for (int i = 0; i < numStreamBytes; i++)
+ {
+ m_data->m_serverDNA[i] = m_data->m_bulletStreamDataServerToClient[i];
+ }
+ }
+ break;
+ }
+ case CMD_RESET_SIMULATION_COMPLETED:
+ {
+ m_data->m_debugLinesFrom.clear();
+ m_data->m_debugLinesTo.clear();
+ m_data->m_debugLinesColor.clear();
+ for (int i = 0; im_bodyJointMap.size(); i++)
+ {
+ BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap.getAtIndex(i);
+ if (bodyJointsPtr && *bodyJointsPtr)
+ {
+ BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
+ for (int j = 0; jm_jointInfo.size(); j++) {
+ if (bodyJoints->m_jointInfo[j].m_jointName)
+ {
+ free(bodyJoints->m_jointInfo[j].m_jointName);
+ }
+ if (bodyJoints->m_jointInfo[j].m_linkName)
+ {
+ free(bodyJoints->m_jointInfo[j].m_linkName);
+ }
+ }
+ delete (*bodyJointsPtr);
+ }
+ }
+ m_data->m_bodyJointMap.clear();
+
+ break;
+ }
+ case CMD_SDF_LOADING_COMPLETED:
+ {
+ //we'll stream further info from the physics server
+ //so serverCmd will be invalid, make a copy
+
+
+ int numBodies = serverCmd.m_sdfLoadedArgs.m_numBodies;
+ for (int i = 0; im_commandProcessor->processCommand(infoRequestCommand, infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ hasStatus = m_data->m_commandProcessor->receiveStatus(infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+ }
+
+ if (hasStatus)
+ {
+ processBodyJointInfo(bodyUniqueId, infoStatus);
+ }
+ }
+ break;
+ }
+ case CMD_URDF_LOADING_COMPLETED:
+ {
+
+ if (serverCmd.m_numDataStreamBytes > 0)
+ {
+ int bodyIndex = serverCmd.m_dataStreamArguments.m_bodyUniqueId;
+ processBodyJointInfo(bodyIndex, serverCmd);
+ }
+ break;
+ }
+ case CMD_BULLET_LOADING_FAILED:
+ {
+ b3Warning("Couldn't load .bullet file");
+ break;
+ }
+ case CMD_BULLET_LOADING_COMPLETED:
+ {
+ break;
+ }
+ case CMD_USER_CONSTRAINT_COMPLETED:
+ {
+ break;
+ }
+ case CMD_USER_CONSTRAINT_FAILED:
+ {
+ b3Warning("createConstraint failed");
+ break;
+ }
+ default:
+ {
+ //b3Warning("Unknown server status type");
+ }
+ };
+
+
+}
bool PhysicsDirect::submitClientCommand(const struct SharedMemoryCommand& command)
{
if (command.m_type==CMD_REQUEST_DEBUG_LINES)
@@ -422,83 +708,16 @@ bool PhysicsDirect::submitClientCommand(const struct SharedMemoryCommand& comman
{
return processVisualShapeData(command);
}
+ if (command.m_type == CMD_REQUEST_AABB_OVERLAP)
+ {
+ return processOverlappingObjects(command);
+ }
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
- const SharedMemoryStatus& serverCmd = m_data->m_serverStatus;
-
- switch (m_data->m_serverStatus.m_type)
- {
- case CMD_RESET_SIMULATION_COMPLETED:
- {
- m_data->m_debugLinesFrom.clear();
- m_data->m_debugLinesTo.clear();
- m_data->m_debugLinesColor.clear();
- for (int i=0;im_bodyJointMap.size();i++)
- {
- BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap.getAtIndex(i);
- if (bodyJointsPtr && *bodyJointsPtr)
- {
- BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
- for (int j=0;jm_jointInfo.size();j++) {
- if (bodyJoints->m_jointInfo[j].m_jointName)
- {
- free(bodyJoints->m_jointInfo[j].m_jointName);
- }
- if (bodyJoints->m_jointInfo[j].m_linkName)
- {
- free(bodyJoints->m_jointInfo[j].m_linkName);
- }
- }
- delete (*bodyJointsPtr);
- }
- }
- m_data->m_bodyJointMap.clear();
-
- break;
- }
- case CMD_SDF_LOADING_COMPLETED:
- {
- //we'll stream further info from the physics server
- //so serverCmd will be invalid, make a copy
-
-
- int numBodies = serverCmd.m_sdfLoadedArgs.m_numBodies;
- for (int i=0;im_commandProcessor->processCommand(infoRequestCommand,infoStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
- if (hasStatus)
- {
- processBodyJointInfo(bodyUniqueId, infoStatus);
- }
- }
- break;
- }
- case CMD_URDF_LOADING_COMPLETED:
- {
-
- if (serverCmd.m_dataStreamArguments.m_streamChunkLength > 0)
- {
- int bodyIndex = serverCmd.m_dataStreamArguments.m_bodyUniqueId;
- processBodyJointInfo(bodyIndex,serverCmd);
- }
- break;
- }
-
- default:
- {
- // b3Error("Unknown server status type");
- }
- };
-
-
+ postProcessStatus(m_data->m_serverStatus);
}
return hasStatus;
}
@@ -549,7 +768,7 @@ bool PhysicsDirect::getJointInfo(int bodyIndex, int jointIndex, struct b3JointIn
if (bodyJointsPtr && *bodyJointsPtr)
{
BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
- if (jointIndex < bodyJoints->m_jointInfo.size())
+ if ((jointIndex >=0) && (jointIndex < bodyJoints->m_jointInfo.size()))
{
info = bodyJoints->m_jointInfo[jointIndex];
return true;
@@ -619,6 +838,14 @@ void PhysicsDirect::getCachedContactPointInformation(struct b3ContactInformation
}
+void PhysicsDirect::getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects)
+{
+ overlappingObjects->m_numOverlappingObjects = m_data->m_cachedOverlappingObjects.size();
+ overlappingObjects->m_overlappingObjects = m_data->m_cachedOverlappingObjects.size() ?
+ &m_data->m_cachedOverlappingObjects[0] : 0;
+}
+
+
void PhysicsDirect::getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo)
{
visualShapesInfo->m_numVisualShapes = m_data->m_cachedVisualShapes.size();
diff --git a/examples/SharedMemory/PhysicsDirect.h b/examples/SharedMemory/PhysicsDirect.h
index 2252da3c3..963281f7e 100644
--- a/examples/SharedMemory/PhysicsDirect.h
+++ b/examples/SharedMemory/PhysicsDirect.h
@@ -7,9 +7,6 @@
#include "PhysicsClient.h"
#include "LinearMath/btVector3.h"
-///todo: the PhysicsClient API was designed with shared memory in mind,
-///now it become more general we need to move out the shared memory specifics away
-///for example naming [disconnectSharedMemory -> disconnect] [ move setSharedMemoryKey to shared memory specific subclass ]
///PhysicsDirect executes the commands directly, without transporting them or having a separate server executing commands
class PhysicsDirect : public PhysicsClient
{
@@ -23,13 +20,17 @@ protected:
bool processContactPointData(const struct SharedMemoryCommand& orgCommand);
+ bool processOverlappingObjects(const struct SharedMemoryCommand& orgCommand);
+
bool processVisualShapeData(const struct SharedMemoryCommand& orgCommand);
void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd);
+ void postProcessStatus(const struct SharedMemoryStatus& serverCmd);
+
public:
- PhysicsDirect();
+ PhysicsDirect(class PhysicsCommandProcessorInterface* physSdk);
virtual ~PhysicsDirect();
@@ -76,8 +77,11 @@ public:
virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData);
+ virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects);
+
virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo);
+
//those 2 APIs are for internal use for visualization
virtual bool connect(struct GUIHelperInterface* guiHelper);
virtual void renderScene();
diff --git a/examples/SharedMemory/PhysicsDirectC_API.cpp b/examples/SharedMemory/PhysicsDirectC_API.cpp
index e5e73b203..61ceef26f 100644
--- a/examples/SharedMemory/PhysicsDirectC_API.cpp
+++ b/examples/SharedMemory/PhysicsDirectC_API.cpp
@@ -2,13 +2,21 @@
#include "PhysicsDirect.h"
+#include "PhysicsServerCommandProcessor.h"
+
//think more about naming. The b3ConnectPhysicsLoopback
b3PhysicsClientHandle b3ConnectPhysicsDirect()
{
- PhysicsDirect* direct = new PhysicsDirect();
+ PhysicsServerCommandProcessor* sdk = new PhysicsServerCommandProcessor;
+
+ PhysicsDirect* direct = new PhysicsDirect(sdk);
bool connected = direct->connect();
return (b3PhysicsClientHandle )direct;
}
+
+
+//
+
diff --git a/examples/SharedMemory/PhysicsLoopBack.cpp b/examples/SharedMemory/PhysicsLoopBack.cpp
index f669dde30..3e9c3d77d 100644
--- a/examples/SharedMemory/PhysicsLoopBack.cpp
+++ b/examples/SharedMemory/PhysicsLoopBack.cpp
@@ -144,4 +144,10 @@ void PhysicsLoopBack::getCachedContactPointInformation(struct b3ContactInformati
void PhysicsLoopBack::getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo)
{
return m_data->m_physicsClient->getCachedVisualShapeInformation(visualShapesInfo);
-}
\ No newline at end of file
+}
+
+void PhysicsLoopBack::getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects)
+{
+ return m_data->m_physicsClient->getCachedOverlappingObjects(overlappingObjects);
+}
+
diff --git a/examples/SharedMemory/PhysicsLoopBack.h b/examples/SharedMemory/PhysicsLoopBack.h
index 42acca718..c9187c4b8 100644
--- a/examples/SharedMemory/PhysicsLoopBack.h
+++ b/examples/SharedMemory/PhysicsLoopBack.h
@@ -62,6 +62,8 @@ public:
virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData);
+ virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects);
+
virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo);
};
diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
index 86d3e2ac5..5425100ef 100644
--- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
+++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
@@ -43,8 +43,13 @@ bool gCloseToKuka=false;
bool gEnableRealTimeSimVR=false;
bool gCreateDefaultRobotAssets = false;
int gInternalSimFlags = 0;
+bool gResetSimulation = 0;
+int gHuskyId = -1;
+btTransform huskyTr = btTransform::getIdentity();
int gCreateObjectSimVR = -1;
+int gEnableKukaControl = 0;
+
btScalar simTimeScalingFactor = 1;
btScalar gRhsClamp = 1.f;
@@ -123,6 +128,17 @@ struct InteralBodyData
}
};
+struct InteralUserConstraintData
+{
+ btTypedConstraint* m_rbConstraint;
+ btMultiBodyConstraint* m_mbConstraint;
+ InteralUserConstraintData()
+ :m_rbConstraint(0),
+ m_mbConstraint(0)
+ {
+ }
+};
+
///todo: templatize this
struct InternalBodyHandle : public InteralBodyData
{
@@ -318,6 +334,45 @@ struct SaveWorldObjectData
std::string m_fileName;
};
+struct MyBroadphaseCallback : public btBroadphaseAabbCallback
+{
+ b3AlignedObjectArray m_bodyUniqueIds;
+ b3AlignedObjectArray m_links;
+
+
+ MyBroadphaseCallback()
+ {
+ }
+ virtual ~MyBroadphaseCallback()
+ {
+ }
+ void clear()
+ {
+ m_bodyUniqueIds.clear();
+ m_links.clear();
+ }
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ btCollisionObject* colObj = (btCollisionObject*)proxy->m_clientObject;
+ btMultiBodyLinkCollider* mbl = btMultiBodyLinkCollider::upcast(colObj);
+ if (mbl)
+ {
+ int bodyUniqueId = mbl->m_multiBody->getUserIndex2();
+ m_bodyUniqueIds.push_back(bodyUniqueId);
+ m_links.push_back(mbl->m_link);
+ return true;
+ }
+ int bodyUniqueId = colObj->getUserIndex2();
+ if (bodyUniqueId >= 0)
+ {
+ m_bodyUniqueIds.push_back(bodyUniqueId);
+ m_links.push_back(mbl->m_link);
+ }
+ return true;
+ }
+};
+
+
struct PhysicsServerCommandProcessorInternalData
{
///handle management
@@ -429,6 +484,10 @@ struct PhysicsServerCommandProcessorInternalData
btAlignedObjectArray m_multiBodyJointFeedbacks;
btHashMap m_inverseDynamicsBodies;
btHashMap m_inverseKinematicsHelpers;
+
+ int m_userConstraintUIDGenerator;
+ btHashMap m_userConstraints;
+
b3AlignedObjectArray m_saveWorldBodyData;
@@ -453,6 +512,8 @@ struct PhysicsServerCommandProcessorInternalData
SharedMemoryDebugDrawer* m_remoteDebugDrawer;
btAlignedObjectArray m_cachedContactPoints;
+ MyBroadphaseCallback m_cachedOverlappingObjects;
+
btAlignedObjectArray m_sdfRecentLoadedBodies;
@@ -491,6 +552,7 @@ struct PhysicsServerCommandProcessorInternalData
m_logPlayback(0),
m_physicsDeltaTime(1./240.),
m_numSimulationSubSteps(0),
+ m_userConstraintUIDGenerator(1),
m_dynamicsWorld(0),
m_remoteDebugDrawer(0),
m_guiHelper(0),
@@ -605,8 +667,6 @@ PhysicsServerCommandProcessor::PhysicsServerCommandProcessor()
m_data = new PhysicsServerCommandProcessorInternalData();
createEmptyDynamicsWorld();
- m_data->m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.00001;
- m_data->m_dynamicsWorld->getSolverInfo().m_numIterations = 100;
}
@@ -647,7 +707,7 @@ void PhysicsServerCommandProcessor::createEmptyDynamicsWorld()
#endif
//Workaround: in a VR application, where we avoid synchronizaing between GFX/Physics threads, we don't want to resize this array, so pre-allocate it
- m_data->m_dynamicsWorld->getCollisionObjectArray().reserve(8192);
+ m_data->m_dynamicsWorld->getCollisionObjectArray().reserve(32768);
m_data->m_remoteDebugDrawer = new SharedMemoryDebugDrawer();
@@ -655,8 +715,25 @@ void PhysicsServerCommandProcessor::createEmptyDynamicsWorld()
m_data->m_dynamicsWorld->setGravity(btVector3(0, 0, 0));
m_data->m_dynamicsWorld->getSolverInfo().m_erp2 = 0.08;
+ m_data->m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.00001;
+ m_data->m_dynamicsWorld->getSolverInfo().m_numIterations = 50;
+ m_data->m_dynamicsWorld->getSolverInfo().m_leastSquaresResidualThreshold = 1e-7;
+
}
+void PhysicsServerCommandProcessor::deleteCachedInverseKinematicsBodies()
+{
+ for (int i = 0; i < m_data->m_inverseKinematicsHelpers.size(); i++)
+ {
+ IKTrajectoryHelper** ikHelperPtr = m_data->m_inverseKinematicsHelpers.getAtIndex(i);
+ if (ikHelperPtr)
+ {
+ IKTrajectoryHelper* ikHelper = *ikHelperPtr;
+ delete ikHelper;
+ }
+ }
+ m_data->m_inverseKinematicsHelpers.clear();
+}
void PhysicsServerCommandProcessor::deleteCachedInverseDynamicsBodies()
{
for (int i = 0; i < m_data->m_inverseDynamicsBodies.size(); i++)
@@ -675,7 +752,7 @@ void PhysicsServerCommandProcessor::deleteCachedInverseDynamicsBodies()
void PhysicsServerCommandProcessor::deleteDynamicsWorld()
{
deleteCachedInverseDynamicsBodies();
-
+ deleteCachedInverseKinematicsBodies();
for (int i=0;im_multiBodyJointFeedbacks.size();i++)
{
@@ -1036,10 +1113,17 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto
UrdfLinkNameMapUtil* util = new UrdfLinkNameMapUtil;
m_data->m_urdfLinkNameMapper.push_back(util);
util->m_mb = mb;
+ for (int i = 0; i < bufferSizeInBytes; i++)
+ {
+ bufferServerToClient[i] = 0xcc;
+ }
util->m_memSerializer = new btDefaultSerializer(bufferSizeInBytes ,(unsigned char*)bufferServerToClient);
//disable serialization of the collision objects (they are too big, and the client likely doesn't need them);
util->m_memSerializer->m_skipPointers.insert(mb->getBaseCollider(),0);
+ util->m_memSerializer->startSerialization();
+
+
bodyHandle->m_linkLocalInertialFrames.reserve(mb->getNumLinks());
for (int i=0;igetNumLinks();i++)
{
@@ -1066,18 +1150,19 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto
std::string* baseName = new std::string(u2b.getLinkName(u2b.getRootLinkIndex()));
m_data->m_strings.push_back(baseName);
-
- util->m_memSerializer->registerNameForPointer(baseName->c_str(),baseName->c_str());
mb->setBaseName(baseName->c_str());
+ util->m_memSerializer->registerNameForPointer(baseName->c_str(),baseName->c_str());
- util->m_memSerializer->insertHeader();
+
int len = mb->calculateSerializeBufferSize();
btChunk* chunk = util->m_memSerializer->allocate(len,1);
const char* structType = mb->serialize(chunk->m_oldPtr, util->m_memSerializer);
util->m_memSerializer->finalizeChunk(chunk,structType,BT_MULTIBODY_CODE,mb);
+
+
return true;
} else
{
@@ -1129,6 +1214,8 @@ int PhysicsServerCommandProcessor::createBodyInfoStream(int bodyUniqueId, char*
m_data->m_urdfLinkNameMapper.push_back(util);
util->m_mb = mb;
util->m_memSerializer = new btDefaultSerializer(bufferSizeInBytes ,(unsigned char*)bufferServerToClient);
+ util->m_memSerializer->startSerialization();
+
//disable serialization of the collision objects (they are too big, and the client likely doesn't need them);
util->m_memSerializer->m_skipPointers.insert(mb->getBaseCollider(),0);
if (mb->getBaseName())
@@ -1147,7 +1234,6 @@ int PhysicsServerCommandProcessor::createBodyInfoStream(int bodyUniqueId, char*
util->m_memSerializer->registerNameForPointer(mb->getBaseName(),mb->getBaseName());
- util->m_memSerializer->insertHeader();
int len = mb->calculateSerializeBufferSize();
btChunk* chunk = util->m_memSerializer->allocate(len,1);
@@ -1187,6 +1273,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
//catch uninitialized cases
serverStatusOut.m_type = CMD_INVALID_STATUS;
+ serverStatusOut.m_numDataStreamBytes = 0;
+ serverStatusOut.m_dataStream = 0;
//consume the command
switch (clientCmd.m_type)
@@ -1244,7 +1332,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
}
//9 floats per line: 3 floats for 'from', 3 floats for 'to' and 3 floats for 'color'
- int maxNumLines = bufferSizeInBytes/(sizeof(float)*9)-1;
+ int bytesPerLine = (sizeof(float) * 9);
+ int maxNumLines = bufferSizeInBytes/bytesPerLine-1;
if (startingLineIndex >m_data->m_remoteDebugDrawer->m_lines2.size())
{
b3Warning("m_startingLineIndex exceeds total number of debug lines");
@@ -1277,7 +1366,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
}
serverStatusOut.m_type = CMD_DEBUG_LINES_COMPLETED;
-
+ serverStatusOut.m_numDataStreamBytes = numLines * bytesPerLine;
serverStatusOut.m_sendDebugLinesArgs.m_numDebugLines = numLines;
serverStatusOut.m_sendDebugLinesArgs.m_startingLineIndex = startingLineIndex;
serverStatusOut.m_sendDebugLinesArgs.m_numRemainingDebugLines = m_data->m_remoteDebugDrawer->m_lines2.size()-(startingLineIndex+numLines);
@@ -1327,6 +1416,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
float* depthBuffer = (float*)(bufferServerToClient+numRequestedPixels*4);
int* segmentationMaskBuffer = (int*)(bufferServerToClient+numRequestedPixels*8);
+ serverStatusOut.m_numDataStreamBytes = numRequestedPixels * totalBytesPerPixel;
+
if ((clientCmd.m_updateFlags & ER_BULLET_HARDWARE_OPENGL)!=0)
{
m_data->m_guiHelper->copyCameraImageData(clientCmd.m_requestPixelDataArguments.m_viewMatrix,
@@ -1341,6 +1432,40 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
{
// printf("-------------------------------\nRendering\n");
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_LIGHT_DIRECTION) != 0)
+ {
+ m_data->m_visualConverter.setLightDirection(clientCmd.m_requestPixelDataArguments.m_lightDirection[0], clientCmd.m_requestPixelDataArguments.m_lightDirection[1], clientCmd.m_requestPixelDataArguments.m_lightDirection[2]);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_LIGHT_COLOR) != 0)
+ {
+ m_data->m_visualConverter.setLightColor(clientCmd.m_requestPixelDataArguments.m_lightColor[0], clientCmd.m_requestPixelDataArguments.m_lightColor[1], clientCmd.m_requestPixelDataArguments.m_lightColor[2]);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_LIGHT_DISTANCE) != 0)
+ {
+ m_data->m_visualConverter.setLightDistance(clientCmd.m_requestPixelDataArguments.m_lightDistance);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_SHADOW) != 0)
+ {
+ m_data->m_visualConverter.setShadow(clientCmd.m_requestPixelDataArguments.m_hasShadow);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_AMBIENT_COEFF) != 0)
+ {
+ m_data->m_visualConverter.setLightAmbientCoeff(clientCmd.m_requestPixelDataArguments.m_lightAmbientCoeff);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_DIFFUSE_COEFF) != 0)
+ {
+ m_data->m_visualConverter.setLightDiffuseCoeff(clientCmd.m_requestPixelDataArguments.m_lightDiffuseCoeff);
+ }
+
+ if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_SET_SPECULAR_COEFF) != 0)
+ {
+ m_data->m_visualConverter.setLightSpecularCoeff(clientCmd.m_requestPixelDataArguments.m_lightSpecularCoeff);
+ }
if ((clientCmd.m_updateFlags & REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES)!=0)
{
@@ -1368,6 +1493,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
}
serverStatusOut.m_type = CMD_CAMERA_IMAGE_COMPLETED;
+
serverStatusOut.m_sendPixelDataArguments.m_numPixelsCopied = numPixelsCopied;
serverStatusOut.m_sendPixelDataArguments.m_numRemainingPixels = numRemainingPixels - numPixelsCopied;
serverStatusOut.m_sendPixelDataArguments.m_startingPixelIndex = startPixelIndex;
@@ -1386,7 +1512,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
serverStatusOut.m_type = CMD_BODY_INFO_COMPLETED;
serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = sdfInfoArgs.m_bodyUniqueId;
- serverStatusOut.m_dataStreamArguments.m_streamChunkLength = streamSizeInBytes;
+ serverStatusOut.m_numDataStreamBytes = streamSizeInBytes;
+
hasStatus = true;
break;
}
@@ -1606,11 +1733,11 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
m_data->m_guiHelper->autogenerateGraphicsObjects(this->m_data->m_dynamicsWorld);
serverStatusOut.m_type = CMD_URDF_LOADING_COMPLETED;
- serverStatusOut.m_dataStreamArguments.m_streamChunkLength = 0;
+
if (m_data->m_urdfLinkNameMapper.size())
{
- serverStatusOut.m_dataStreamArguments.m_streamChunkLength = m_data->m_urdfLinkNameMapper.at(m_data->m_urdfLinkNameMapper.size()-1)->m_memSerializer->getCurrentBufferSize();
+ serverStatusOut.m_numDataStreamBytes = m_data->m_urdfLinkNameMapper.at(m_data->m_urdfLinkNameMapper.size()-1)->m_memSerializer->getCurrentBufferSize();
}
serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = bodyUniqueId;
hasStatus = true;
@@ -1629,6 +1756,21 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
case CMD_LOAD_BUNNY:
{
#ifdef USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD
+ double scale = 0.1;
+ double mass = 0.1;
+ double collisionMargin = 0.02;
+ if (clientCmd.m_updateFlags & LOAD_BUNNY_UPDATE_SCALE)
+ {
+ scale = clientCmd.m_loadBunnyArguments.m_scale;
+ }
+ if (clientCmd.m_updateFlags & LOAD_BUNNY_UPDATE_MASS)
+ {
+ mass = clientCmd.m_loadBunnyArguments.m_mass;
+ }
+ if (clientCmd.m_updateFlags & LOAD_BUNNY_UPDATE_COLLISION_MARGIN)
+ {
+ collisionMargin = clientCmd.m_loadBunnyArguments.m_collisionMargin;
+ }
m_data->m_softBodyWorldInfo.air_density = (btScalar)1.2;
m_data->m_softBodyWorldInfo.water_density = 0;
m_data->m_softBodyWorldInfo.water_offset = 0;
@@ -1643,14 +1785,14 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
pm->m_kLST = 1.0;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
- psb->m_cfg.piterations = 2;
+ psb->m_cfg.piterations = 50;
psb->m_cfg.kDF = 0.5;
psb->randomizeConstraints();
psb->rotate(btQuaternion(0.70711,0,0,0.70711));
- psb->translate(btVector3(0,0,3.0));
- psb->scale(btVector3(0.1,0.1,0.1));
- psb->setTotalMass(1,true);
- psb->getCollisionShape()->setMargin(0.01);
+ psb->translate(btVector3(0,0,1.0));
+ psb->scale(btVector3(scale,scale,scale));
+ psb->setTotalMass(mass,true);
+ psb->getCollisionShape()->setMargin(collisionMargin);
m_data->m_dynamicsWorld->addSoftBody(psb);
#endif
@@ -2156,6 +2298,28 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
break;
}
+ case CMD_REQUEST_INTERNAL_DATA:
+ {
+ //todo: also check version etc?
+
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+ serverCmd.m_type = CMD_REQUEST_INTERNAL_DATA_FAILED;
+ hasStatus = true;
+
+ int sz = btDefaultSerializer::getMemoryDnaSizeInBytes();
+ const char* memDna = btDefaultSerializer::getMemoryDna();
+ if (sz < bufferSizeInBytes)
+ {
+ for (int i = 0; i < sz; i++)
+ {
+ bufferServerToClient[i] = memDna[i];
+ }
+ serverCmd.m_type = CMD_REQUEST_INTERNAL_DATA_COMPLETED;
+ serverCmd.m_numDataStreamBytes = sz;
+ }
+
+ break;
+ };
case CMD_SEND_PHYSICS_SIMULATION_PARAMETERS:
{
if (clientCmd.m_updateFlags&SIM_PARAM_UPDATE_DELTA_TIME)
@@ -2191,6 +2355,17 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
{
m_data->m_dynamicsWorld->getSolverInfo().m_numIterations = clientCmd.m_physSimParamArgs.m_numSolverIterations;
}
+
+ if (clientCmd.m_updateFlags & SIM_PARAM_UPDATE_USE_SPLIT_IMPULSE)
+ {
+ m_data->m_dynamicsWorld->getSolverInfo().m_splitImpulse = clientCmd.m_physSimParamArgs.m_useSplitImpulse;
+ }
+ if (clientCmd.m_updateFlags &SIM_PARAM_UPDATE_SPLIT_IMPULSE_PENETRATION_THRESHOLD)
+ {
+ m_data->m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = clientCmd.m_physSimParamArgs.m_splitImpulsePenetrationThreshold;
+ }
+
+
if (clientCmd.m_updateFlags&SIM_PARAM_UPDATE_NUM_SIMULATION_SUB_STEPS)
{
m_data->m_numSimulationSubSteps = clientCmd.m_physSimParamArgs.m_numSimulationSubSteps;
@@ -2216,9 +2391,54 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
int bodyUniqueId = clientCmd.m_initPoseArgs.m_bodyUniqueId;
InteralBodyData* body = m_data->getHandle(bodyUniqueId);
+ btVector3 baseLinVel(0, 0, 0);
+ btVector3 baseAngVel(0, 0, 0);
+
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_LINEAR_VELOCITY)
+ {
+ baseLinVel.setValue(clientCmd.m_initPoseArgs.m_initialStateQdot[0],
+ clientCmd.m_initPoseArgs.m_initialStateQdot[1],
+ clientCmd.m_initPoseArgs.m_initialStateQdot[2]);
+ }
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_ANGULAR_VELOCITY)
+ {
+ baseAngVel.setValue(clientCmd.m_initPoseArgs.m_initialStateQdot[3],
+ clientCmd.m_initPoseArgs.m_initialStateQdot[4],
+ clientCmd.m_initPoseArgs.m_initialStateQdot[5]);
+ }
+ btVector3 basePos(0, 0, 0);
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_POSITION)
+ {
+ basePos = btVector3(
+ clientCmd.m_initPoseArgs.m_initialStateQ[0],
+ clientCmd.m_initPoseArgs.m_initialStateQ[1],
+ clientCmd.m_initPoseArgs.m_initialStateQ[2]);
+ }
+ btQuaternion baseOrn(0, 0, 0, 1);
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_ORIENTATION)
+ {
+ baseOrn.setValue(clientCmd.m_initPoseArgs.m_initialStateQ[3],
+ clientCmd.m_initPoseArgs.m_initialStateQ[4],
+ clientCmd.m_initPoseArgs.m_initialStateQ[5],
+ clientCmd.m_initPoseArgs.m_initialStateQ[6]);
+ }
if (body && body->m_multiBody)
{
btMultiBody* mb = body->m_multiBody;
+
+
+
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_LINEAR_VELOCITY)
+ {
+ mb->setBaseVel(baseLinVel);
+ }
+
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_ANGULAR_VELOCITY)
+ {
+ mb->setBaseOmega(baseAngVel);
+ }
+
+
if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_POSITION)
{
btVector3 zero(0,0,0);
@@ -2226,11 +2446,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
clientCmd.m_initPoseArgs.m_hasInitialStateQ[1] &&
clientCmd.m_initPoseArgs.m_hasInitialStateQ[2]);
- mb->setBaseVel(zero);
- mb->setBasePos(btVector3(
- clientCmd.m_initPoseArgs.m_initialStateQ[0],
- clientCmd.m_initPoseArgs.m_initialStateQ[1],
- clientCmd.m_initPoseArgs.m_initialStateQ[2]));
+ mb->setBaseVel(baseLinVel);
+ mb->setBasePos(basePos);
}
if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_ORIENTATION)
{
@@ -2239,11 +2456,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
clientCmd.m_initPoseArgs.m_hasInitialStateQ[5] &&
clientCmd.m_initPoseArgs.m_hasInitialStateQ[6]);
- mb->setBaseOmega(btVector3(0,0,0));
- btQuaternion invOrn(clientCmd.m_initPoseArgs.m_initialStateQ[3],
- clientCmd.m_initPoseArgs.m_initialStateQ[4],
- clientCmd.m_initPoseArgs.m_initialStateQ[5],
- clientCmd.m_initPoseArgs.m_initialStateQ[6]);
+ mb->setBaseOmega(baseAngVel);
+ btQuaternion invOrn(baseOrn);
mb->setWorldToBaseRot(invOrn.inverse());
}
@@ -2260,6 +2474,43 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
dofIndex += mb->getLink(i).m_dofCount;
}
}
+
+ btAlignedObjectArray scratch_q;
+ btAlignedObjectArray scratch_m;
+
+ mb->forwardKinematics(scratch_q,scratch_m);
+ int nLinks = mb->getNumLinks();
+ scratch_q.resize(nLinks+1);
+ scratch_m.resize(nLinks+1);
+
+ mb->updateCollisionObjectWorldTransforms(scratch_q,scratch_m);
+
+
+ }
+
+ if (body && body->m_rigidBody)
+ {
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_LINEAR_VELOCITY)
+ {
+ body->m_rigidBody->setLinearVelocity(baseLinVel);
+ }
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_BASE_ANGULAR_VELOCITY)
+ {
+ body->m_rigidBody->setAngularVelocity(baseAngVel);
+ }
+
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_POSITION)
+ {
+ body->m_rigidBody->getWorldTransform().setOrigin(basePos);
+ body->m_rigidBody->setLinearVelocity(baseLinVel);
+ }
+
+ if (clientCmd.m_updateFlags & INIT_POSE_HAS_INITIAL_ORIENTATION)
+ {
+ body->m_rigidBody->getWorldTransform().setRotation(baseOrn);
+ body->m_rigidBody->setAngularVelocity(baseAngVel);
+ }
+
}
SharedMemoryStatus& serverCmd =serverStatusOut;
@@ -2272,29 +2523,12 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
case CMD_RESET_SIMULATION:
{
- //clean up all data
- deleteCachedInverseDynamicsBodies();
-
- if (m_data && m_data->m_guiHelper)
- {
- m_data->m_guiHelper->removeAllGraphicsInstances();
- }
- if (m_data)
- {
- m_data->m_visualConverter.resetAll();
- }
-
- deleteDynamicsWorld();
- createEmptyDynamicsWorld();
-
- m_data->exitHandles();
- m_data->initHandles();
+
+ resetSimulation();
SharedMemoryStatus& serverCmd =serverStatusOut;
serverCmd.m_type = CMD_RESET_SIMULATION_COMPLETED;
hasStatus = true;
- m_data->m_hasGround = false;
- m_data->m_gripperRigidbodyFixed = 0;
break;
}
case CMD_CREATE_RIGID_BODY:
@@ -2470,92 +2704,339 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
hasStatus = true;
break;
}
+ case CMD_REQUEST_AABB_OVERLAP:
+ {
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+ int curObjectIndex = clientCmd.m_requestOverlappingObjectsArgs.m_startingOverlappingObjectIndex;
+
+ if (0== curObjectIndex)
+ {
+ //clientCmd.m_requestContactPointArguments.m_aabbQueryMin
+ btVector3 aabbMin, aabbMax;
+ aabbMin.setValue(clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMin[0],
+ clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMin[1],
+ clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMin[2]);
+ aabbMax.setValue(clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMax[0],
+ clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMax[1],
+ clientCmd.m_requestOverlappingObjectsArgs.m_aabbQueryMax[2]);
+
+ m_data->m_cachedOverlappingObjects.clear();
+
+ m_data->m_dynamicsWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, m_data->m_cachedOverlappingObjects);
+ }
+
+
+ int totalBytesPerObject = sizeof(b3OverlappingObject);
+ int overlapCapacity = bufferSizeInBytes / totalBytesPerObject - 1;
+ int numOverlap = m_data->m_cachedOverlappingObjects.m_bodyUniqueIds.size();
+ int remainingObjects = numOverlap - curObjectIndex;
+
+ int curNumObjects = btMin(overlapCapacity, remainingObjects);
+
+ if (numOverlap < overlapCapacity)
+ {
+
+ b3OverlappingObject* overlapStorage = (b3OverlappingObject*)bufferServerToClient;
+ for (int i = 0; i < m_data->m_cachedOverlappingObjects.m_bodyUniqueIds.size(); i++)
+ {
+ overlapStorage[i].m_objectUniqueId = m_data->m_cachedOverlappingObjects.m_bodyUniqueIds[i];
+ overlapStorage[i].m_linkIndex = m_data->m_cachedOverlappingObjects.m_links[i];
+ }
+
+ serverCmd.m_type = CMD_REQUEST_AABB_OVERLAP_COMPLETED;
+
+ int m_startingOverlappingObjectIndex;
+ int m_numOverlappingObjectsCopied;
+ int m_numRemainingOverlappingObjects;
+ serverCmd.m_sendOverlappingObjectsArgs.m_startingOverlappingObjectIndex = clientCmd.m_requestOverlappingObjectsArgs.m_startingOverlappingObjectIndex;
+ serverCmd.m_sendOverlappingObjectsArgs.m_numOverlappingObjectsCopied = m_data->m_cachedOverlappingObjects.m_bodyUniqueIds.size();
+ serverCmd.m_sendOverlappingObjectsArgs.m_numRemainingOverlappingObjects = remainingObjects - curNumObjects;
+ }
+ else
+ {
+ serverCmd.m_type = CMD_REQUEST_AABB_OVERLAP_FAILED;
+ }
+
+ hasStatus = true;
+ break;
+ }
case CMD_REQUEST_CONTACT_POINT_INFORMATION:
{
SharedMemoryStatus& serverCmd =serverStatusOut;
serverCmd.m_sendContactPointArgs.m_numContactPointsCopied = 0;
//make a snapshot of the contact manifolds into individual contact points
- if (clientCmd.m_requestContactPointArguments.m_startingContactPointIndex==0)
- {
- int numContactManifolds = m_data->m_dynamicsWorld->getDispatcher()->getNumManifolds();
+ if (clientCmd.m_requestContactPointArguments.m_startingContactPointIndex == 0)
+ {
m_data->m_cachedContactPoints.resize(0);
- m_data->m_cachedContactPoints.reserve(numContactManifolds*4);
- for (int i=0;im_dynamicsWorld->getDispatcher()->getInternalManifoldPointer()[i];
- int linkIndexA = -1;
- int linkIndexB = -1;
-
- int objectIndexB = -1;
- const btRigidBody* bodyB = btRigidBody::upcast(manifold->getBody1());
- if (bodyB)
+ int mode = CONTACT_QUERY_MODE_REPORT_EXISTING_CONTACT_POINTS;
+
+ if (clientCmd.m_updateFlags & CMD_REQUEST_CONTACT_POINT_HAS_QUERY_MODE)
+ {
+ mode = clientCmd.m_requestContactPointArguments.m_mode;
+ }
+
+ switch (mode)
+ {
+ case CONTACT_QUERY_MODE_REPORT_EXISTING_CONTACT_POINTS:
+ {
+ int numContactManifolds = m_data->m_dynamicsWorld->getDispatcher()->getNumManifolds();
+ m_data->m_cachedContactPoints.reserve(numContactManifolds * 4);
+ for (int i = 0; i < numContactManifolds; i++)
{
- objectIndexB = bodyB->getUserIndex2();
- }
- const btMultiBodyLinkCollider* mblB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
- if (mblB && mblB->m_multiBody)
- {
- linkIndexB = mblB->m_link;
- objectIndexB = mblB->m_multiBody->getUserIndex2();
- }
+ const btPersistentManifold* manifold = m_data->m_dynamicsWorld->getDispatcher()->getInternalManifoldPointer()[i];
+ int linkIndexA = -1;
+ int linkIndexB = -1;
- int objectIndexA = -1;
- const btRigidBody* bodyA = btRigidBody::upcast(manifold->getBody0());
- if (bodyA)
- {
- objectIndexA = bodyA->getUserIndex2();
- }
- const btMultiBodyLinkCollider* mblA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- if (mblA && mblA->m_multiBody)
- {
- linkIndexA = mblA->m_link;
+ int objectIndexB = -1;
- objectIndexA = mblA->m_multiBody->getUserIndex2();
- }
-
- btAssert(bodyA || mblA);
-
- //apply the filter, if the user provides it
- if (clientCmd.m_requestContactPointArguments.m_objectAIndexFilter>=0)
- {
- if ((clientCmd.m_requestContactPointArguments.m_objectAIndexFilter != objectIndexA) &&
- (clientCmd.m_requestContactPointArguments.m_objectAIndexFilter != objectIndexB))
- continue;
- }
-
- //apply the second object filter, if the user provides it
- if (clientCmd.m_requestContactPointArguments.m_objectBIndexFilter>=0)
- {
- if ((clientCmd.m_requestContactPointArguments.m_objectBIndexFilter != objectIndexA) &&
- (clientCmd.m_requestContactPointArguments.m_objectBIndexFilter != objectIndexB))
- continue;
- }
-
- for (int p=0;pgetNumContacts();p++)
- {
-
- b3ContactPointData pt;
- pt.m_bodyUniqueIdA = objectIndexA;
- pt.m_bodyUniqueIdB = objectIndexB;
- const btManifoldPoint& srcPt = manifold->getContactPoint(p);
- pt.m_contactDistance = srcPt.getDistance();
- pt.m_contactFlags = 0;
- pt.m_linkIndexA = linkIndexA;
- pt.m_linkIndexB = linkIndexB;
- for (int j=0;j<3;j++)
+ const btRigidBody* bodyB = btRigidBody::upcast(manifold->getBody1());
+ if (bodyB)
{
- pt.m_contactNormalOnBInWS[j] = srcPt.m_normalWorldOnB[j];
- pt.m_positionOnAInWS[j] = srcPt.getPositionWorldOnA()[j];
- pt.m_positionOnBInWS[j] = srcPt.getPositionWorldOnB()[j];
+ objectIndexB = bodyB->getUserIndex2();
+ }
+ const btMultiBodyLinkCollider* mblB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+ if (mblB && mblB->m_multiBody)
+ {
+ linkIndexB = mblB->m_link;
+ objectIndexB = mblB->m_multiBody->getUserIndex2();
+ }
+
+ int objectIndexA = -1;
+ const btRigidBody* bodyA = btRigidBody::upcast(manifold->getBody0());
+ if (bodyA)
+ {
+ objectIndexA = bodyA->getUserIndex2();
+ }
+ const btMultiBodyLinkCollider* mblA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ if (mblA && mblA->m_multiBody)
+ {
+ linkIndexA = mblA->m_link;
+
+ objectIndexA = mblA->m_multiBody->getUserIndex2();
+ }
+
+ btAssert(bodyA || mblA);
+
+ //apply the filter, if the user provides it
+ if (clientCmd.m_requestContactPointArguments.m_objectAIndexFilter >= 0)
+ {
+ if ((clientCmd.m_requestContactPointArguments.m_objectAIndexFilter != objectIndexA) &&
+ (clientCmd.m_requestContactPointArguments.m_objectAIndexFilter != objectIndexB))
+ continue;
+ }
+
+ //apply the second object filter, if the user provides it
+ if (clientCmd.m_requestContactPointArguments.m_objectBIndexFilter >= 0)
+ {
+ if ((clientCmd.m_requestContactPointArguments.m_objectBIndexFilter != objectIndexA) &&
+ (clientCmd.m_requestContactPointArguments.m_objectBIndexFilter != objectIndexB))
+ continue;
+ }
+
+ for (int p = 0; p < manifold->getNumContacts(); p++)
+ {
+
+ b3ContactPointData pt;
+ pt.m_bodyUniqueIdA = objectIndexA;
+ pt.m_bodyUniqueIdB = objectIndexB;
+ const btManifoldPoint& srcPt = manifold->getContactPoint(p);
+ pt.m_contactDistance = srcPt.getDistance();
+ pt.m_contactFlags = 0;
+ pt.m_linkIndexA = linkIndexA;
+ pt.m_linkIndexB = linkIndexB;
+ for (int j = 0; j < 3; j++)
+ {
+ pt.m_contactNormalOnBInWS[j] = srcPt.m_normalWorldOnB[j];
+ pt.m_positionOnAInWS[j] = srcPt.getPositionWorldOnA()[j];
+ pt.m_positionOnBInWS[j] = srcPt.getPositionWorldOnB()[j];
+ }
+ pt.m_normalForce = srcPt.getAppliedImpulse() / m_data->m_physicsDeltaTime;
+ // pt.m_linearFrictionForce = srcPt.m_appliedImpulseLateral1;
+ m_data->m_cachedContactPoints.push_back(pt);
}
- pt.m_normalForce = srcPt.getAppliedImpulse()/m_data->m_physicsDeltaTime;
-// pt.m_linearFrictionForce = srcPt.m_appliedImpulseLateral1;
- m_data->m_cachedContactPoints.push_back (pt);
}
- }
- }
+ break;
+ }
+
+ case CONTACT_QUERY_MODE_COMPUTE_CLOSEST_POINTS:
+ {
+ //todo(erwincoumans) compute closest points between all, and vs all, pair
+ btScalar closestDistanceThreshold = 0.f;
+
+ if (clientCmd.m_updateFlags & CMD_REQUEST_CONTACT_POINT_HAS_CLOSEST_DISTANCE_THRESHOLD)
+ {
+ closestDistanceThreshold = clientCmd.m_requestContactPointArguments.m_closestDistanceThreshold;
+ }
+
+ int bodyUniqueIdA = clientCmd.m_requestContactPointArguments.m_objectAIndexFilter;
+ int bodyUniqueIdB = clientCmd.m_requestContactPointArguments.m_objectBIndexFilter;
+
+ bool hasLinkIndexAFilter = (0!=(clientCmd.m_updateFlags & CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_A_FILTER));
+ bool hasLinkIndexBFilter = (0!=(clientCmd.m_updateFlags & CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_B_FILTER));
+
+ int linkIndexA = clientCmd.m_requestContactPointArguments.m_linkIndexAIndexFilter;
+ int linkIndexB = clientCmd.m_requestContactPointArguments.m_linkIndexBIndexFilter;
+
+ btAlignedObjectArray setA;
+ btAlignedObjectArray setB;
+ btAlignedObjectArray setALinkIndex;
+ btAlignedObjectArray setBLinkIndex;
+
+ if (bodyUniqueIdA >= 0)
+ {
+ InteralBodyData* bodyA = m_data->getHandle(bodyUniqueIdA);
+ if (bodyA)
+ {
+ if (bodyA->m_multiBody)
+ {
+ if (bodyA->m_multiBody->getBaseCollider())
+ {
+ if (!hasLinkIndexAFilter || (linkIndexA == -1))
+ {
+ setA.push_back(bodyA->m_multiBody->getBaseCollider());
+ setALinkIndex.push_back(-1);
+ }
+ }
+ for (int i = 0; i < bodyA->m_multiBody->getNumLinks(); i++)
+ {
+ if (bodyA->m_multiBody->getLink(i).m_collider)
+ {
+ if (!hasLinkIndexAFilter || (linkIndexA == i))
+ {
+ setA.push_back(bodyA->m_multiBody->getLink(i).m_collider);
+ setALinkIndex.push_back(i);
+ }
+ }
+ }
+ }
+ if (bodyA->m_rigidBody)
+ {
+ setA.push_back(bodyA->m_rigidBody);
+ setALinkIndex.push_back(-1);
+ }
+ }
+ }
+ if (bodyUniqueIdB>=0)
+ {
+ InteralBodyData* bodyB = m_data->getHandle(bodyUniqueIdB);
+ if (bodyB)
+ {
+ if (bodyB->m_multiBody)
+ {
+ if (bodyB->m_multiBody->getBaseCollider())
+ {
+ if (!hasLinkIndexBFilter || (linkIndexB == -1))
+ {
+ setB.push_back(bodyB->m_multiBody->getBaseCollider());
+ setBLinkIndex.push_back(-1);
+ }
+ }
+ for (int i = 0; i < bodyB->m_multiBody->getNumLinks(); i++)
+ {
+ if (bodyB->m_multiBody->getLink(i).m_collider)
+ {
+ if (!hasLinkIndexBFilter || (linkIndexB ==i))
+ {
+ setB.push_back(bodyB->m_multiBody->getLink(i).m_collider);
+ setBLinkIndex.push_back(i);
+ }
+ }
+ }
+ }
+ if (bodyB->m_rigidBody)
+ {
+ setB.push_back(bodyB->m_rigidBody);
+ setBLinkIndex.push_back(-1);
+
+ }
+ }
+ }
+
+ {
+ ///ContactResultCallback is used to report contact points
+ struct MyContactResultCallback : public btCollisionWorld::ContactResultCallback
+ {
+ //short int m_collisionFilterGroup;
+ //short int m_collisionFilterMask;
+ int m_bodyUniqueIdA;
+ int m_bodyUniqueIdB;
+ int m_linkIndexA;
+ int m_linkIndexB;
+ btScalar m_deltaTime;
+
+ btAlignedObjectArray& m_cachedContactPoints;
+
+ MyContactResultCallback(btAlignedObjectArray& pointCache)
+ :m_cachedContactPoints(pointCache)
+ {
+ }
+
+ virtual ~MyContactResultCallback()
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ //bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ //collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ //return collides;
+ return true;
+ }
+
+ virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1)
+ {
+ b3ContactPointData pt;
+ pt.m_bodyUniqueIdA = m_bodyUniqueIdA;
+ pt.m_bodyUniqueIdB = m_bodyUniqueIdB;
+ const btManifoldPoint& srcPt = cp;
+ pt.m_contactDistance = srcPt.getDistance();
+ pt.m_contactFlags = 0;
+ pt.m_linkIndexA = m_linkIndexA;
+ pt.m_linkIndexB = m_linkIndexB;
+ for (int j = 0; j < 3; j++)
+ {
+ pt.m_contactNormalOnBInWS[j] = srcPt.m_normalWorldOnB[j];
+ pt.m_positionOnAInWS[j] = srcPt.getPositionWorldOnA()[j];
+ pt.m_positionOnBInWS[j] = srcPt.getPositionWorldOnB()[j];
+ }
+ pt.m_normalForce = srcPt.getAppliedImpulse() / m_deltaTime;
+ // pt.m_linearFrictionForce = srcPt.m_appliedImpulseLateral1;
+ m_cachedContactPoints.push_back(pt);
+
+ return 1;
+ }
+ };
+
+
+ MyContactResultCallback cb(m_data->m_cachedContactPoints);
+
+ cb.m_bodyUniqueIdA = bodyUniqueIdA;
+ cb.m_bodyUniqueIdB = bodyUniqueIdB;
+ cb.m_deltaTime = m_data->m_physicsDeltaTime;
+
+ for (int i = 0; i < setA.size(); i++)
+ {
+ cb.m_linkIndexA = setALinkIndex[i];
+ for (int j = 0; j < setB.size(); j++)
+ {
+ cb.m_linkIndexB = setBLinkIndex[j];
+ cb.m_closestDistanceThreshold = closestDistanceThreshold;
+ this->m_data->m_dynamicsWorld->contactPairTest(setA[i], setB[j], cb);
+ }
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ b3Warning("Unknown contact query mode: %d", mode);
+ }
+
+ }
+ }
int numContactPoints = m_data->m_cachedContactPoints.size();
@@ -2583,7 +3064,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
serverCmd.m_sendContactPointArgs.m_startingContactPointIndex = clientCmd.m_requestContactPointArguments.m_startingContactPointIndex;
serverCmd.m_sendContactPointArgs.m_numRemainingContactPoints = numContactPoints - clientCmd.m_requestContactPointArguments.m_startingContactPointIndex - serverCmd.m_sendContactPointArgs.m_numContactPointsCopied;
-
+ serverCmd.m_numDataStreamBytes = totalBytesPerContact * serverCmd.m_sendContactPointArgs.m_numContactPointsCopied;
serverCmd.m_type = CMD_CONTACT_POINT_INFORMATION_COMPLETED; //CMD_CONTACT_POINT_INFORMATION_FAILED,
hasStatus = true;
break;
@@ -2703,11 +3184,12 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
for (int i = 0; i < clientCmd.m_externalForceArguments.m_numForcesAndTorques; ++i)
{
InteralBodyData* body = m_data->getHandle(clientCmd.m_externalForceArguments.m_bodyUniqueIds[i]);
+ bool isLinkFrame = ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_LINK_FRAME) != 0);
+
if (body && body->m_multiBody)
{
btMultiBody* mb = body->m_multiBody;
- bool isLinkFrame = ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_LINK_FRAME)!=0);
-
+
if ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_FORCE)!=0)
{
btVector3 forceLocal(clientCmd.m_externalForceArguments.m_forcesAndTorques[i*3+0],
@@ -2755,6 +3237,36 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
}
}
}
+
+ if (body && body->m_rigidBody)
+ {
+ btRigidBody* rb = body->m_rigidBody;
+ if ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_FORCE) != 0)
+ {
+ btVector3 forceLocal(clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 0],
+ clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 1],
+ clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 2]);
+ btVector3 positionLocal(
+ clientCmd.m_externalForceArguments.m_positions[i * 3 + 0],
+ clientCmd.m_externalForceArguments.m_positions[i * 3 + 1],
+ clientCmd.m_externalForceArguments.m_positions[i * 3 + 2]);
+
+ btVector3 forceWorld = isLinkFrame ? forceLocal : rb->getWorldTransform().getBasis()*forceLocal;
+ btVector3 relPosWorld = isLinkFrame ? positionLocal : rb->getWorldTransform().getBasis()*positionLocal;
+ rb->applyForce(forceWorld, relPosWorld);
+
+ }
+
+ if ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_TORQUE) != 0)
+ {
+ btVector3 torqueLocal(clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 0],
+ clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 1],
+ clientCmd.m_externalForceArguments.m_forcesAndTorques[i * 3 + 2]);
+
+ btVector3 torqueWorld = isLinkFrame ? torqueLocal : rb->getWorldTransform().getBasis()*torqueLocal;
+ rb->applyTorque(torqueWorld);
+ }
+ }
}
SharedMemoryStatus& serverCmd =serverStatusOut;
@@ -2762,72 +3274,144 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
hasStatus = true;
break;
}
- case CMD_CREATE_JOINT:
+ case CMD_USER_CONSTRAINT:
{
- InteralBodyData* parentBody = m_data->getHandle(clientCmd.m_createJointArguments.m_parentBodyIndex);
- if (parentBody && parentBody->m_multiBody)
- {
- InteralBodyData* childBody = m_data->getHandle(clientCmd.m_createJointArguments.m_childBodyIndex);
- if (childBody)
- {
- btVector3 pivotInParent(clientCmd.m_createJointArguments.m_parentFrame[0], clientCmd.m_createJointArguments.m_parentFrame[1], clientCmd.m_createJointArguments.m_parentFrame[2]);
- btVector3 pivotInChild(clientCmd.m_createJointArguments.m_childFrame[0], clientCmd.m_createJointArguments.m_childFrame[1], clientCmd.m_createJointArguments.m_childFrame[2]);
- btMatrix3x3 frameInParent(btQuaternion(clientCmd.m_createJointArguments.m_parentFrame[3], clientCmd.m_createJointArguments.m_parentFrame[4], clientCmd.m_createJointArguments.m_parentFrame[5], clientCmd.m_createJointArguments.m_parentFrame[6]));
- btMatrix3x3 frameInChild(btQuaternion(clientCmd.m_createJointArguments.m_childFrame[3], clientCmd.m_createJointArguments.m_childFrame[4], clientCmd.m_createJointArguments.m_childFrame[5], clientCmd.m_createJointArguments.m_childFrame[6]));
- btVector3 jointAxis(clientCmd.m_createJointArguments.m_jointAxis[0], clientCmd.m_createJointArguments.m_jointAxis[1], clientCmd.m_createJointArguments.m_jointAxis[2]);
- if (clientCmd.m_createJointArguments.m_jointType == eFixedType)
- {
- if (childBody->m_multiBody)
- {
- btMultiBodyFixedConstraint* multibodyFixed = new btMultiBodyFixedConstraint(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_createJointArguments.m_childJointIndex,pivotInParent,pivotInChild,frameInParent,frameInChild);
- multibodyFixed->setMaxAppliedImpulse(500.0);
- m_data->m_dynamicsWorld->addMultiBodyConstraint(multibodyFixed);
- }
- else
- {
- btMultiBodyFixedConstraint* rigidbodyFixed = new btMultiBodyFixedConstraint(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild,frameInParent,frameInChild);
- rigidbodyFixed->setMaxAppliedImpulse(500.0);
- btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
- world->addMultiBodyConstraint(rigidbodyFixed);
- }
- }
- else if (clientCmd.m_createJointArguments.m_jointType == ePrismaticType)
- {
- if (childBody->m_multiBody)
- {
- btMultiBodySliderConstraint* multibodySlider = new btMultiBodySliderConstraint(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_createJointArguments.m_childJointIndex,pivotInParent,pivotInChild,frameInParent,frameInChild,jointAxis);
- multibodySlider->setMaxAppliedImpulse(500.0);
- m_data->m_dynamicsWorld->addMultiBodyConstraint(multibodySlider);
- }
- else
- {
- btMultiBodySliderConstraint* rigidbodySlider = new btMultiBodySliderConstraint(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild,frameInParent,frameInChild,jointAxis);
- rigidbodySlider->setMaxAppliedImpulse(500.0);
- btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
- world->addMultiBodyConstraint(rigidbodySlider);
- }
- } else if (clientCmd.m_createJointArguments.m_jointType == ePoint2PointType)
- {
- if (childBody->m_multiBody)
- {
- btMultiBodyPoint2Point* p2p = new btMultiBodyPoint2Point(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_createJointArguments.m_childJointIndex,pivotInParent,pivotInChild);
- p2p->setMaxAppliedImpulse(500);
- m_data->m_dynamicsWorld->addMultiBodyConstraint(p2p);
- }
- else
- {
- btMultiBodyPoint2Point* p2p = new btMultiBodyPoint2Point(parentBody->m_multiBody,clientCmd.m_createJointArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild);
- p2p->setMaxAppliedImpulse(500);
- btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
- world->addMultiBodyConstraint(p2p);
- }
- }
-
- }
- }
SharedMemoryStatus& serverCmd =serverStatusOut;
- serverCmd.m_type = CMD_CLIENT_COMMAND_COMPLETED;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_FAILED;
hasStatus = true;
+
+ if (clientCmd.m_updateFlags & USER_CONSTRAINT_ADD_CONSTRAINT)
+ {
+ InteralBodyData* parentBody = m_data->getHandle(clientCmd.m_userConstraintArguments.m_parentBodyIndex);
+ if (parentBody && parentBody->m_multiBody)
+ {
+ InteralBodyData* childBody = m_data->getHandle(clientCmd.m_userConstraintArguments.m_childBodyIndex);
+ if (childBody)
+ {
+ btVector3 pivotInParent(clientCmd.m_userConstraintArguments.m_parentFrame[0], clientCmd.m_userConstraintArguments.m_parentFrame[1], clientCmd.m_userConstraintArguments.m_parentFrame[2]);
+ btVector3 pivotInChild(clientCmd.m_userConstraintArguments.m_childFrame[0], clientCmd.m_userConstraintArguments.m_childFrame[1], clientCmd.m_userConstraintArguments.m_childFrame[2]);
+ btMatrix3x3 frameInParent(btQuaternion(clientCmd.m_userConstraintArguments.m_parentFrame[3], clientCmd.m_userConstraintArguments.m_parentFrame[4], clientCmd.m_userConstraintArguments.m_parentFrame[5], clientCmd.m_userConstraintArguments.m_parentFrame[6]));
+ btMatrix3x3 frameInChild(btQuaternion(clientCmd.m_userConstraintArguments.m_childFrame[3], clientCmd.m_userConstraintArguments.m_childFrame[4], clientCmd.m_userConstraintArguments.m_childFrame[5], clientCmd.m_userConstraintArguments.m_childFrame[6]));
+ btVector3 jointAxis(clientCmd.m_userConstraintArguments.m_jointAxis[0], clientCmd.m_userConstraintArguments.m_jointAxis[1], clientCmd.m_userConstraintArguments.m_jointAxis[2]);
+ if (clientCmd.m_userConstraintArguments.m_jointType == eFixedType)
+ {
+ if (childBody->m_multiBody)
+ {
+ btMultiBodyFixedConstraint* multibodyFixed = new btMultiBodyFixedConstraint(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_userConstraintArguments.m_childJointIndex,pivotInParent,pivotInChild,frameInParent,frameInChild);
+ multibodyFixed->setMaxAppliedImpulse(500.0);
+ m_data->m_dynamicsWorld->addMultiBodyConstraint(multibodyFixed);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = multibodyFixed;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+
+ }
+ else
+ {
+ btMultiBodyFixedConstraint* rigidbodyFixed = new btMultiBodyFixedConstraint(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild,frameInParent,frameInChild);
+ rigidbodyFixed->setMaxAppliedImpulse(500.0);
+ btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
+ world->addMultiBodyConstraint(rigidbodyFixed);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = rigidbodyFixed;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+
+ }
+ else if (clientCmd.m_userConstraintArguments.m_jointType == ePrismaticType)
+ {
+ if (childBody->m_multiBody)
+ {
+ btMultiBodySliderConstraint* multibodySlider = new btMultiBodySliderConstraint(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_userConstraintArguments.m_childJointIndex,pivotInParent,pivotInChild,frameInParent,frameInChild,jointAxis);
+ multibodySlider->setMaxAppliedImpulse(500.0);
+ m_data->m_dynamicsWorld->addMultiBodyConstraint(multibodySlider);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = multibodySlider;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+ else
+ {
+ btMultiBodySliderConstraint* rigidbodySlider = new btMultiBodySliderConstraint(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild,frameInParent,frameInChild,jointAxis);
+ rigidbodySlider->setMaxAppliedImpulse(500.0);
+ btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
+ world->addMultiBodyConstraint(rigidbodySlider);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = rigidbodySlider;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+
+ } else if (clientCmd.m_userConstraintArguments.m_jointType == ePoint2PointType)
+ {
+ if (childBody->m_multiBody)
+ {
+ btMultiBodyPoint2Point* p2p = new btMultiBodyPoint2Point(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_multiBody,clientCmd.m_userConstraintArguments.m_childJointIndex,pivotInParent,pivotInChild);
+ p2p->setMaxAppliedImpulse(500);
+ m_data->m_dynamicsWorld->addMultiBodyConstraint(p2p);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = p2p;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+ else
+ {
+ btMultiBodyPoint2Point* p2p = new btMultiBodyPoint2Point(parentBody->m_multiBody,clientCmd.m_userConstraintArguments.m_parentJointIndex,childBody->m_rigidBody,pivotInParent,pivotInChild);
+ p2p->setMaxAppliedImpulse(500);
+ btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_data->m_dynamicsWorld;
+ world->addMultiBodyConstraint(p2p);
+ InteralUserConstraintData userConstraintData;
+ userConstraintData.m_mbConstraint = p2p;
+ int uid = m_data->m_userConstraintUIDGenerator++;
+ m_data->m_userConstraints.insert(uid,userConstraintData);
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = uid;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+
+ } else
+ {
+ b3Warning("unknown constraint type");
+ }
+
+
+ }
+ }
+ }
+
+ if (clientCmd.m_updateFlags & USER_CONSTRAINT_REMOVE_CONSTRAINT)
+ {
+ int userConstraintUidRemove = clientCmd.m_userConstraintArguments.m_userConstraintUniqueId;
+ InteralUserConstraintData* userConstraintPtr = m_data->m_userConstraints.find(userConstraintUidRemove);
+ if (userConstraintPtr)
+ {
+ if (userConstraintPtr->m_mbConstraint)
+ {
+ m_data->m_dynamicsWorld->removeMultiBodyConstraint(userConstraintPtr->m_mbConstraint);
+ delete userConstraintPtr->m_mbConstraint;
+ m_data->m_userConstraints.remove(userConstraintUidRemove);
+ }
+ if (userConstraintPtr->m_rbConstraint)
+ {
+
+ }
+ serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId = -1;
+ serverCmd.m_type = CMD_USER_CONSTRAINT_COMPLETED;
+ }
+
+
+ }
+
break;
}
case CMD_CALCULATE_INVERSE_KINEMATICS:
@@ -3006,7 +3590,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied = 1;
serverCmd.m_sendVisualShapeArgs.m_startingVisualShapeIndex = clientCmd.m_requestVisualShapeDataArguments.m_startingVisualShapeIndex;
serverCmd.m_sendVisualShapeArgs.m_bodyUniqueId = clientCmd.m_requestVisualShapeDataArguments.m_bodyUniqueId;
-
+ serverCmd.m_numDataStreamBytes = sizeof(b3VisualShapeData)*serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied;
serverCmd.m_type =CMD_VISUAL_SHAPE_INFO_COMPLETED;
hasStatus = true;
break;
@@ -3028,14 +3612,220 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
SharedMemoryStatus& serverCmd = serverStatusOut;
serverCmd.m_type = CMD_LOAD_TEXTURE_FAILED;
- m_data->m_visualConverter.loadTextureFile(clientCmd.m_loadTextureArguments.m_textureFileName);
+ int uid = m_data->m_visualConverter.loadTextureFile(clientCmd.m_loadTextureArguments.m_textureFileName);
- serverCmd.m_type = CMD_LOAD_TEXTURE_COMPLETED;
+ if (uid>=0)
+ {
+ serverCmd.m_type = CMD_LOAD_TEXTURE_COMPLETED;
+ } else
+ {
+ serverCmd.m_type = CMD_LOAD_TEXTURE_FAILED;
+ }
hasStatus = true;
break;
}
+ case CMD_LOAD_BULLET:
+ {
+
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+ btBulletWorldImporter* importer = new btBulletWorldImporter(m_data->m_dynamicsWorld);
+
+ const char* prefix[] = { "", "./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/" };
+ int numPrefixes = sizeof(prefix) / sizeof(const char*);
+ char relativeFileName[1024];
+ FILE* f = 0;
+ bool found = false;
+
+ for (int i = 0; !f && iloadFile(relativeFileName);
+ if (ok)
+ {
+
+
+ int numRb = importer->getNumRigidBodies();
+ serverStatusOut.m_sdfLoadedArgs.m_numBodies = 0;
+
+ for( int i=0;igetRigidBodyByIndex(i);
+ if (colObj)
+ {
+ btRigidBody* rb = btRigidBody::upcast(colObj);
+ if (rb)
+ {
+ int bodyUniqueId = m_data->allocHandle();
+ InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId);
+ colObj->setUserIndex2(bodyUniqueId);
+ bodyHandle->m_rigidBody = rb;
+
+ if (serverStatusOut.m_sdfLoadedArgs.m_numBodiesm_guiHelper->autogenerateGraphicsObjects(m_data->m_dynamicsWorld);
+ hasStatus = true;
+ break;
+ }
+ }
+ serverCmd.m_type = CMD_BULLET_LOADING_FAILED;
+ hasStatus = true;
+ break;
+ }
+
+ case CMD_SAVE_BULLET:
+ {
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+
+ FILE* f = fopen(clientCmd.m_fileArguments.m_fileName, "wb");
+ if (f)
+ {
+ btDefaultSerializer* ser = new btDefaultSerializer();
+ m_data->m_dynamicsWorld->serialize(ser);
+ fwrite(ser->getBufferPointer(), ser->getCurrentBufferSize(), 1, f);
+ fclose(f);
+ serverCmd.m_type = CMD_BULLET_SAVING_COMPLETED;
+ delete ser;
+ }
+ serverCmd.m_type = CMD_BULLET_SAVING_FAILED;
+ hasStatus = true;
+ break;
+ }
+
+ case CMD_LOAD_MJCF:
+ {
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+ serverCmd.m_type = CMD_MJCF_LOADING_FAILED;
+ hasStatus = true;
+ break;
+ }
+
+ case CMD_USER_DEBUG_DRAW:
+ {
+ SharedMemoryStatus& serverCmd = serverStatusOut;
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_FAILED;
+ hasStatus = true;
+
+ if ((clientCmd.m_updateFlags & USER_DEBUG_SET_CUSTOM_OBJECT_COLOR) || (clientCmd.m_updateFlags & USER_DEBUG_REMOVE_CUSTOM_OBJECT_COLOR))
+ {
+ int bodyUniqueId = clientCmd.m_userDebugDrawArgs.m_objectUniqueId;
+ InteralBodyData* body = m_data->getHandle(bodyUniqueId);
+ if (body)
+ {
+ btCollisionObject* destColObj = 0;
+
+ if (body->m_multiBody)
+ {
+ if (clientCmd.m_userDebugDrawArgs.m_linkIndex == -1)
+ {
+ destColObj = body->m_multiBody->getBaseCollider();
+ }
+ else
+ {
+ if (clientCmd.m_userDebugDrawArgs.m_linkIndex >= 0 && clientCmd.m_userDebugDrawArgs.m_linkIndex < body->m_multiBody->getNumLinks())
+ {
+ destColObj = body->m_multiBody->getLink(clientCmd.m_userDebugDrawArgs.m_linkIndex).m_collider;
+ }
+ }
+
+ }
+ if (body->m_rigidBody)
+ {
+ destColObj = body->m_rigidBody;
+ }
+
+ if (destColObj)
+ {
+ if (clientCmd.m_updateFlags & USER_DEBUG_REMOVE_CUSTOM_OBJECT_COLOR)
+ {
+ destColObj->removeCustomDebugColor();
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+ }
+ if (clientCmd.m_updateFlags & USER_DEBUG_SET_CUSTOM_OBJECT_COLOR)
+ {
+ btVector3 objectColorRGB;
+ objectColorRGB.setValue(clientCmd.m_userDebugDrawArgs.m_objectDebugColorRGB[0],
+ clientCmd.m_userDebugDrawArgs.m_objectDebugColorRGB[1],
+ clientCmd.m_userDebugDrawArgs.m_objectDebugColorRGB[2]);
+ destColObj->setCustomDebugColor(objectColorRGB);
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+ }
+ }
+ }
+ }
+
+ if (clientCmd.m_updateFlags & USER_DEBUG_HAS_TEXT)
+ {
+ int uid = m_data->m_guiHelper->addUserDebugText3D(clientCmd.m_userDebugDrawArgs.m_text,
+ clientCmd.m_userDebugDrawArgs.m_textPositionXYZ,
+ clientCmd.m_userDebugDrawArgs.m_textColorRGB,
+ clientCmd.m_userDebugDrawArgs.m_textSize,
+ clientCmd.m_userDebugDrawArgs.m_lifeTime);
+
+ if (uid>=0)
+ {
+ serverCmd.m_userDebugDrawArgs.m_debugItemUniqueId = uid;
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+ }
+ }
+
+ if (clientCmd.m_updateFlags & USER_DEBUG_HAS_LINE)
+ {
+ int uid = m_data->m_guiHelper->addUserDebugLine(
+ clientCmd.m_userDebugDrawArgs.m_debugLineFromXYZ,
+ clientCmd.m_userDebugDrawArgs.m_debugLineToXYZ,
+ clientCmd.m_userDebugDrawArgs.m_debugLineColorRGB,
+ clientCmd.m_userDebugDrawArgs.m_lineWidth,
+ clientCmd.m_userDebugDrawArgs.m_lifeTime);
+
+ if (uid>=0)
+ {
+ serverCmd.m_userDebugDrawArgs.m_debugItemUniqueId = uid;
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+ }
+ }
+
+
+ if (clientCmd.m_updateFlags & USER_DEBUG_REMOVE_ALL)
+ {
+ m_data->m_guiHelper->removeAllUserDebugItems();
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+
+ }
+ if (clientCmd.m_updateFlags & USER_DEBUG_REMOVE_ONE_ITEM)
+ {
+ m_data->m_guiHelper->removeUserDebugItem(clientCmd.m_userDebugDrawArgs.m_removeItemUniqueId);
+ serverCmd.m_type = CMD_USER_DEBUG_DRAW_COMPLETED;
+
+ }
+
+ break;
+ }
+
+
default:
{
b3Error("Unknown command encountered");
@@ -3091,6 +3881,7 @@ void PhysicsServerCommandProcessor::physicsDebugDraw(int debugDrawFlags)
bool PhysicsServerCommandProcessor::pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
{
+
if (m_data->m_dynamicsWorld==0)
return false;
@@ -3124,7 +3915,7 @@ bool PhysicsServerCommandProcessor::pickBody(const btVector3& rayFromWorld, cons
} else
{
btMultiBodyLinkCollider* multiCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(rayCallback.m_collisionObject);
- if (multiCol && multiCol->m_multiBody)
+ if (multiCol && multiCol->m_multiBody && multiCol->m_multiBody->getBaseMass()>0.)
{
m_data->m_prevCanSleep = multiCol->m_multiBody->getCanSleep();
@@ -3241,7 +4032,7 @@ void PhysicsServerCommandProcessor::replayFromLogFile(const char* fileName)
}
-btVector3 gVRGripperPos(0,0,0.2);
+btVector3 gVRGripperPos(0.6, 0.4, 0.7);
btQuaternion gVRGripperOrn(0,0,0,1);
btVector3 gVRController2Pos(0,0,0.2);
btQuaternion gVRController2Orn(0,0,0,1);
@@ -3255,9 +4046,21 @@ int gDroppedSimulationSteps = 0;
int gNumSteps = 0;
double gDtInSec = 0.f;
double gSubStep = 0.f;
+
+void PhysicsServerCommandProcessor::enableRealTimeSimulation(bool enableRealTimeSim)
+{
+ m_data->m_allowRealTimeSimulation = enableRealTimeSim;
+}
+
void PhysicsServerCommandProcessor::stepSimulationRealTime(double dtInSec)
{
- if ((gEnableRealTimeSimVR || m_data->m_allowRealTimeSimulation) && m_data->m_guiHelper)
+ if (gResetSimulation)
+ {
+ resetSimulation();
+ gResetSimulation = false;
+ }
+
+ if ((m_data->m_allowRealTimeSimulation) && m_data->m_guiHelper)
{
///this hardcoded C++ scene creation is temporary for demo purposes. It will be done in Python later...
@@ -3276,6 +4079,16 @@ void PhysicsServerCommandProcessor::stepSimulationRealTime(double dtInSec)
gSubStep = m_data->m_physicsDeltaTime;
}
+ if (gHuskyId >= 0)
+ {
+ InternalBodyHandle* bodyHandle = m_data->getHandle(gHuskyId);
+ if (bodyHandle && bodyHandle->m_multiBody)
+ {
+ huskyTr = bodyHandle->m_multiBody->getBaseWorldTransform();
+ }
+ }
+
+
int numSteps = m_data->m_dynamicsWorld->stepSimulation(dtInSec*simTimeScalingFactor,maxSteps, gSubStep);
gDroppedSimulationSteps += numSteps > maxSteps ? numSteps - maxSteps : 0;
@@ -3304,7 +4117,30 @@ void PhysicsServerCommandProcessor::applyJointDamping(int bodyUniqueId)
}
}
+void PhysicsServerCommandProcessor::resetSimulation()
+{
+ //clean up all data
+ deleteCachedInverseDynamicsBodies();
+ if (m_data && m_data->m_guiHelper)
+ {
+ m_data->m_guiHelper->removeAllGraphicsInstances();
+ }
+ if (m_data)
+ {
+ m_data->m_visualConverter.resetAll();
+ }
+
+ deleteDynamicsWorld();
+ createEmptyDynamicsWorld();
+
+ m_data->exitHandles();
+ m_data->initHandles();
+
+ m_data->m_hasGround = false;
+ m_data->m_gripperRigidbodyFixed = 0;
+
+}
//todo: move this to Python/scripting
void PhysicsServerCommandProcessor::createDefaultRobotAssets()
{
@@ -3336,12 +4172,13 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
loadUrdf("plane.urdf", btVector3(0, 0, 0), btQuaternion(0, 0, 0, 1), true, true, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
loadUrdf("samurai.urdf", btVector3(0, 0, 0), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
+// loadUrdf("quadruped/quadruped.urdf", btVector3(2, 2, 1), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
if (m_data->m_gripperRigidbodyFixed == 0)
{
int bodyId = 0;
- if (loadUrdf("pr2_gripper.urdf", btVector3(0, 0, 0.1), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size()))
+ if (loadUrdf("pr2_gripper.urdf", btVector3(-0.2, 0.15, 0.9), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size()))
{
InteralBodyData* parentBody = m_data->getHandle(bodyId);
if (parentBody->m_multiBody)
@@ -3371,6 +4208,30 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
loadUrdf("kuka_iiwa/model_vr_limits.urdf", btVector3(1.4, -0.2, 0.6), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
m_data->m_KukaId = bodyId;
+ InteralBodyData* kukaBody = m_data->getHandle(m_data->m_KukaId);
+ if (kukaBody->m_multiBody && kukaBody->m_multiBody->getNumDofs() == 7)
+ {
+ btScalar q[7];
+ q[0] = 0;// -SIMD_HALF_PI;
+ q[1] = 0;
+ q[2] = 0;
+ q[3] = SIMD_HALF_PI;
+ q[4] = 0;
+ q[5] = -SIMD_HALF_PI*0.66;
+ q[6] = 0;
+
+ for (int i = 0; i < 7; i++)
+ {
+ kukaBody->m_multiBody->setJointPos(i, q[i]);
+ }
+ btAlignedObjectArray scratch_q;
+ btAlignedObjectArray scratch_m;
+ kukaBody->m_multiBody->forwardKinematics(scratch_q, scratch_m);
+ int nLinks = kukaBody->m_multiBody->getNumLinks();
+ scratch_q.resize(nLinks + 1);
+ scratch_m.resize(nLinks + 1);
+ kukaBody->m_multiBody->updateCollisionObjectWorldTransforms(scratch_q, scratch_m);
+ }
loadUrdf("lego/lego.urdf", btVector3(1.0, -0.2, .7), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
loadUrdf("lego/lego.urdf", btVector3(1.0, -0.2, .8), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
loadUrdf("lego/lego.urdf", btVector3(1.0, -0.2, .9), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
@@ -3379,7 +4240,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
// Load one motor gripper for kuka
loadSdf("gripper/wsg50_one_motor_gripper_new_free_base.sdf", &gBufferServerToClient[0], gBufferServerToClient.size(), true);
m_data->m_gripperId = bodyId + 1;
- InteralBodyData* kukaBody = m_data->getHandle(m_data->m_KukaId);
+
InteralBodyData* gripperBody = m_data->getHandle(m_data->m_gripperId);
// Reset the default gripper motor maximum torque for damping to 0
@@ -3421,6 +4282,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
m_data->m_dynamicsWorld->addMultiBodyConstraint(m_data->m_kukaGripperRevolute1);
m_data->m_dynamicsWorld->addMultiBodyConstraint(m_data->m_kukaGripperRevolute2);
+ kukaBody = m_data->getHandle(m_data->m_KukaId);
if (kukaBody->m_multiBody && kukaBody->m_multiBody->getNumDofs()==7)
{
gripperBody->m_multiBody->setHasSelfCollision(0);
@@ -3447,7 +4309,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
btTransform objectLocalTr[] = {
btTransform(btQuaternion(0, 0, 0, 1), btVector3(0.0, 0.0, 0.0)),
- btTransform(btQuaternion(0, 0, 0, 1), btVector3(0.0, 0.15, 0.64)),
+ btTransform(btQuaternion(btVector3(0,0,1),-SIMD_HALF_PI), btVector3(0.0, 0.15, 0.64)),
btTransform(btQuaternion(0, 0, 0, 1), btVector3(0.1, 0.15, 0.85)),
btTransform(btQuaternion(0, 0, 0, 1), btVector3(-0.4, 0.05, 0.85)),
btTransform(btQuaternion(0, 0, 0, 1), btVector3(-0.3, -0.05, 0.7)),
@@ -3474,7 +4336,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
// Table area
loadUrdf("table/table.urdf", objectWorldTr[0].getOrigin(), objectWorldTr[0].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
- loadUrdf("tray.urdf", objectWorldTr[1].getOrigin(), objectWorldTr[1].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
+ //loadUrdf("tray/tray_textured.urdf", objectWorldTr[1].getOrigin(), objectWorldTr[1].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
//loadUrdf("cup_small.urdf", objectWorldTr[2].getOrigin(), objectWorldTr[2].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
//loadUrdf("pitcher_small.urdf", objectWorldTr[3].getOrigin(), objectWorldTr[3].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
loadUrdf("teddy_vhacd.urdf", objectWorldTr[4].getOrigin(), objectWorldTr[4].getRotation(), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
@@ -3498,7 +4360,9 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
//loadUrdf("rook.urdf", btVector3(-1.2, 0, 0.7), btQuaternion(btVector3(1, 0, 0), SIMD_HALF_PI), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
//loadUrdf("knight.urdf", btVector3(-1.2, 0.2, 0.7), btQuaternion(btVector3(1, 0, 0), SIMD_HALF_PI), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
- //loadUrdf("husky/husky.urdf", btVector3(2, -5, 1), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
+ loadUrdf("husky/husky.urdf", btVector3(2, -5, 1), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size());
+ gHuskyId = bodyId;
+ b3Printf("huskyId = %d", gHuskyId);
m_data->m_huskyId = bodyId;
m_data->m_dynamicsWorld->setGravity(btVector3(0, 0, -10));
@@ -3513,9 +4377,10 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
if (motor)
{
btScalar posTarget = (-0.048)*btMin(btScalar(0.75), gVRGripper2Analog) / 0.75;
- motor->setPositionTarget(posTarget, .2);
+ motor->setPositionTarget(posTarget, .8);
motor->setVelocityTarget(0.0, .5);
- motor->setMaxAppliedImpulse(5.0);
+ motor->setMaxAppliedImpulse(1.0);
+
}
}
@@ -3523,6 +4388,8 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
{
m_data->m_gripperRigidbodyFixed->setFrameInB(btMatrix3x3(gVRGripperOrn));
m_data->m_gripperRigidbodyFixed->setPivotInB(gVRGripperPos);
+ btScalar avg = 0.f;
+
for (int i = 0; i < m_data->m_gripperMultiBody->getNumLinks(); i++)
{
if (supportsJointMotor(m_data->m_gripperMultiBody, i))
@@ -3533,7 +4400,14 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
motor->setErp(0.2);
btScalar posTarget = 0.1 + (1 - btMin(btScalar(0.75),gVRGripperAnalog)*btScalar(1.5))*SIMD_HALF_PI*0.29;
btScalar maxPosTarget = 0.55;
-
+
+ btScalar correction = 0.f;
+
+ if (avg)
+ {
+ correction = m_data->m_gripperMultiBody->getJointPos(i) - avg;
+ }
+
if (m_data->m_gripperMultiBody->getJointPos(i) < 0)
{
m_data->m_gripperMultiBody->setJointPos(i,0);
@@ -3543,10 +4417,19 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
m_data->m_gripperMultiBody->setJointPos(i, maxPosTarget);
}
- motor->setPositionTarget(posTarget, 1);
+ if (avg)
+ {
+ motor->setPositionTarget(avg, 1);
+ }
+ else
+ {
+ motor->setPositionTarget(posTarget, 1);
+ }
motor->setVelocityTarget(0, 0.5);
- btScalar maxImp = 1*m_data->m_physicsDeltaTime;
+ btScalar maxImp = (1+0.1*i)*m_data->m_physicsDeltaTime;
motor->setMaxAppliedImpulse(maxImp);
+ avg = m_data->m_gripperMultiBody->getJointPos(i);
+
//motor->setRhsClamp(gRhsClamp);
}
}
@@ -3554,7 +4437,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
}
// Inverse kinematics for KUKA
- //if (0)
+ if (m_data->m_KukaId>=0)
{
InternalBodyHandle* bodyHandle = m_data->getHandle(m_data->m_KukaId);
if (bodyHandle && bodyHandle->m_multiBody && bodyHandle->m_multiBody->getNumDofs()==7)
@@ -3583,7 +4466,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
q_new[5] = -SIMD_HALF_PI*0.66;
q_new[6] = 0;
- if (gCloseToKuka)
+ if (gCloseToKuka && gEnableKukaControl)
{
double dampIk[6] = {1.0, 1.0, 1.0, 1.0, 1.0, 0.0};
@@ -3730,6 +4613,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
}
//directly set the position of the links, only for debugging IK, don't use this method!
+#if 0
if (0)
{
for (int i=0;igetNumLinks();i++)
@@ -3738,6 +4622,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
mb->setJointPosMultiDof(i,&desiredPosition);
}
} else
+#endif
{
int numMotors = 0;
//find the joint motors and apply the desired velocity and maximum force/torque
@@ -3772,4 +4657,4 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets()
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.h b/examples/SharedMemory/PhysicsServerCommandProcessor.h
index 2814d11dd..c8a060069 100644
--- a/examples/SharedMemory/PhysicsServerCommandProcessor.h
+++ b/examples/SharedMemory/PhysicsServerCommandProcessor.h
@@ -3,6 +3,8 @@
#include "LinearMath/btVector3.h"
+#include "PhysicsCommandProcessorInterface.h"
+
struct SharedMemLines
{
btVector3 m_from;
@@ -10,8 +12,10 @@ struct SharedMemLines
btVector3 m_color;
};
+
+
///todo: naming. Perhaps PhysicsSdkCommandprocessor?
-class PhysicsServerCommandProcessor
+class PhysicsServerCommandProcessor : public PhysicsCommandProcessorInterface
{
struct PhysicsServerCommandProcessorInternalData* m_data;
@@ -19,32 +23,53 @@ class PhysicsServerCommandProcessor
//todo: move this to physics client side / Python
void createDefaultRobotAssets();
+ void resetSimulation();
+
protected:
-
- bool loadSdf(const char* fileName, char* bufferServerToClient, int bufferSizeInBytes, bool useMultiBody);
+
+ bool loadSdf(const char* fileName, char* bufferServerToClient, int bufferSizeInBytes, bool useMultiBody);
bool loadUrdf(const char* fileName, const class btVector3& pos, const class btQuaternion& orn,
- bool useMultiBody, bool useFixedBase, int* bodyUniqueIdPtr, char* bufferServerToClient, int bufferSizeInBytes);
+ bool useMultiBody, bool useFixedBase, int* bodyUniqueIdPtr, char* bufferServerToClient, int bufferSizeInBytes);
bool supportsJointMotor(class btMultiBody* body, int linkIndex);
-
+
int createBodyInfoStream(int bodyUniqueId, char* bufferServerToClient, int bufferSizeInBytes);
void deleteCachedInverseDynamicsBodies();
+ void deleteCachedInverseKinematicsBodies();
public:
PhysicsServerCommandProcessor();
virtual ~PhysicsServerCommandProcessor();
void createJointMotors(class btMultiBody* body);
-
+
virtual void createEmptyDynamicsWorld();
virtual void deleteDynamicsWorld();
-
- virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes );
+ virtual bool connect()
+ {
+ return true;
+ };
+
+ virtual void disconnect() {}
+
+ virtual bool isConnected() const
+ {
+ return true;
+ }
+
+
+
+ virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
+
+ virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
+ {
+ return false;
+ };
virtual void renderScene();
virtual void physicsDebugDraw(int debugDrawFlags);
@@ -60,6 +85,7 @@ public:
void replayFromLogFile(const char* fileName);
void replayLogCommand(char* bufferServerToClient, int bufferSizeInBytes );
void stepSimulationRealTime(double dtInSec);
+ void enableRealTimeSimulation(bool enableRealTimeSim);
void applyJointDamping(int bodyUniqueId);
};
diff --git a/examples/SharedMemory/PhysicsServerExample.cpp b/examples/SharedMemory/PhysicsServerExample.cpp
index 77eaa6cd9..2bc823d3b 100644
--- a/examples/SharedMemory/PhysicsServerExample.cpp
+++ b/examples/SharedMemory/PhysicsServerExample.cpp
@@ -4,7 +4,9 @@
#include "PhysicsServerExample.h"
-
+#ifdef B3_USE_MIDI
+#include "RtMidi.h"
+#endif//B3_USE_MIDI
#include "PhysicsServerSharedMemory.h"
#include "Bullet3Common/b3CommandLineArgs.h"
@@ -24,7 +26,8 @@
//@todo(erwincoumans) those globals are hacks for a VR demo, move this to Python/pybullet!
extern btVector3 gLastPickPos;
-btVector3 gVRTeleportPos(0,0,0);
+btVector3 gVRTeleportPos1(0,0,0);
+btScalar gVRTeleportRotZ = 0;
btQuaternion gVRTeleportOrn(0, 0, 0,1);
extern btVector3 gVRGripperPos;
extern btQuaternion gVRGripperOrn;
@@ -37,11 +40,100 @@ extern bool gEnableRealTimeSimVR;
extern bool gCreateDefaultRobotAssets;
extern int gInternalSimFlags;
extern int gCreateObjectSimVR;
-static int gGraspingController = -1;
+extern bool gResetSimulation;
+extern int gEnableKukaControl;
+int gGraspingController = -1;
extern btScalar simTimeScalingFactor;
extern bool gVRGripperClosed;
+const char* startFileNameVR = "0_VRDemoSettings.txt";
+
+#include
+
+//remember the settings (you don't want to re-tune again and again...)
+static void saveCurrentSettingsVR()
+{
+ FILE* f = fopen(startFileNameVR, "w");
+ if (f)
+ {
+ fprintf(f, "--camPosX= %f\n", gVRTeleportPos1[0]);
+ fprintf(f, "--camPosY= %f\n", gVRTeleportPos1[1]);
+ fprintf(f, "--camPosZ= %f\n", gVRTeleportPos1[2]);
+ fprintf(f, "--camRotZ= %f\n", gVRTeleportRotZ);
+ fclose(f);
+ }
+};
+
+static void loadCurrentSettingsVR(b3CommandLineArgs& args)
+{
+ int currentEntry = 0;
+ FILE* f = fopen(startFileNameVR, "r");
+ if (f)
+ {
+ char oneline[1024];
+ char* argv[] = { 0,&oneline[0] };
+
+ while (fgets(oneline, 1024, f) != NULL)
+ {
+ char *pos;
+ if ((pos = strchr(oneline, '\n')) != NULL)
+ *pos = '\0';
+ args.addArgs(2, argv);
+ }
+ fclose(f);
+ }
+
+};
+#if B3_USE_MIDI
+
+
+static float getParamf(float rangeMin, float rangeMax, int midiVal)
+{
+ float v = rangeMin + (rangeMax - rangeMin)* (float(midiVal / 127.));
+ return v;
+}
+void midiCallback(double deltatime, std::vector< unsigned char > *message, void *userData)
+{
+ unsigned int nBytes = message->size();
+ for (unsigned int i = 0; iat(i) << ", ";
+ if (nBytes > 0)
+ std::cout << "stamp = " << deltatime << std::endl;
+
+ if (nBytes > 2)
+ {
+
+ if (message->at(0) == 176)
+ {
+ if (message->at(1) == 16)
+ {
+ gVRTeleportRotZ= getParamf(-3.1415, 3.1415, message->at(2));
+ gVRTeleportOrn = btQuaternion(btVector3(0, 0, 1), gVRTeleportRotZ);
+ saveCurrentSettingsVR();
+ b3Printf("gVRTeleportOrn rotZ = %f\n", gVRTeleportRotZ);
+ }
+
+ if (message->at(1) == 32)
+ {
+ gCreateDefaultRobotAssets = 1;
+ }
+
+ for (int i = 0; i < 3; i++)
+ {
+ if (message->at(1) == i)
+ {
+ gVRTeleportPos1[i] = getParamf(-2, 2, message->at(2));
+ saveCurrentSettingsVR();
+ b3Printf("gVRTeleportPos[%d] = %f\n", i,gVRTeleportPos1[i]);
+
+ }
+ }
+ }
+ }
+}
+
+#endif //B3_USE_MIDI
bool gDebugRenderToggle = false;
void MotionThreadFunc(void* userPtr,void* lsMemory);
@@ -74,6 +166,11 @@ enum MultiThreadedGUIHelperCommunicationEnums
eGUIHelperCreateRigidBodyGraphicsObject,
eGUIHelperRemoveAllGraphicsInstances,
eGUIHelperCopyCameraImageData,
+ eGUIHelperAutogenerateGraphicsObjects,
+ eGUIUserDebugAddText,
+ eGUIUserDebugAddLine,
+ eGUIUserDebugRemoveItem,
+ eGUIUserDebugRemoveAllItems,
};
#include
@@ -107,7 +204,19 @@ b3ThreadSupportInterface* createMotionThreadSupport(int numThreads)
}
#endif
+enum MyMouseCommandType
+{
+ MyMouseMove = 1,
+ MyMouseButtonDown,
+ MyMouseButtonUp
+};
+struct MyMouseCommand
+{
+ btVector3 m_rayFrom;
+ btVector3 m_rayTo;
+ int m_type;
+};
struct MotionArgs
{
@@ -123,6 +232,8 @@ struct MotionArgs
}
}
b3CriticalSection* m_cs;
+
+ btAlignedObjectArray m_mouseCommands;
PhysicsServerSharedMemory* m_physicsServerPtr;
b3AlignedObjectArray m_positions;
@@ -192,31 +303,31 @@ void MotionThreadFunc(void* userPtr,void* lsMemory)
btMatrix3x3 mat(args->m_vrControllerOrn[c]);
btScalar pickDistance = 1000.;
- btVector3 toX = from+mat.getColumn(0);
- btVector3 toY = from+mat.getColumn(1);
- btVector3 toZ = from+mat.getColumn(2)*pickDistance;
+ btVector3 to = from+mat.getColumn(0)*pickDistance;
+// btVector3 toY = from+mat.getColumn(1)*pickDistance;
+// btVector3 toZ = from+mat.getColumn(2)*pickDistance;
if (args->m_isVrControllerTeleporting[c])
{
args->m_isVrControllerTeleporting[c] = false;
- args->m_physicsServerPtr->pickBody(from,-toZ);
+ args->m_physicsServerPtr->pickBody(from, to);
args->m_physicsServerPtr->removePickingConstraint();
}
- if (!gCloseToKuka)
+// if (!gEnableKukaControl)
{
if (args->m_isVrControllerPicking[c])
{
args->m_isVrControllerPicking[c] = false;
args->m_isVrControllerDragging[c] = true;
- args->m_physicsServerPtr->pickBody(from,-toZ);
+ args->m_physicsServerPtr->pickBody(from, to);
//printf("PICK!\n");
}
}
if (args->m_isVrControllerDragging[c])
{
- args->m_physicsServerPtr->movePickedBody(from,-toZ);
+ args->m_physicsServerPtr->movePickedBody(from, to);
// printf(".");
}
@@ -242,6 +353,37 @@ void MotionThreadFunc(void* userPtr,void* lsMemory)
}
+ args->m_cs->lock();
+ for (int i = 0; i < args->m_mouseCommands.size(); i++)
+ {
+ switch (args->m_mouseCommands[i].m_type)
+ {
+ case MyMouseMove:
+ {
+ args->m_physicsServerPtr->movePickedBody(args->m_mouseCommands[i].m_rayFrom, args->m_mouseCommands[i].m_rayTo);
+ break;
+ };
+ case MyMouseButtonDown:
+ {
+ args->m_physicsServerPtr->pickBody(args->m_mouseCommands[i].m_rayFrom, args->m_mouseCommands[i].m_rayTo);
+ break;
+ }
+ case MyMouseButtonUp:
+ {
+ args->m_physicsServerPtr->removePickingConstraint();
+ break;
+ }
+
+ default:
+ {
+ }
+
+ }
+ }
+ args->m_mouseCommands.clear();
+ args->m_cs->unlock();
+
+
args->m_physicsServerPtr->processClientCommands();
} while (args->m_cs->getSharedParam(0)!=eRequestTerminateMotion);
@@ -270,17 +412,44 @@ void* MotionlsMemoryFunc()
+struct UserDebugDrawLine
+{
+ double m_debugLineFromXYZ[3];
+ double m_debugLineToXYZ[3];
+ double m_debugLineColorRGB[3];
+ double m_lineWidth;
+
+ double m_lifeTime;
+ int m_itemUniqueId;
+};
+
+struct UserDebugText
+{
+ char m_text[1024];
+ double m_textPositionXYZ[3];
+ double m_textColorRGB[3];
+ double textSize;
+
+ double m_lifeTime;
+ int m_itemUniqueId;
+};
+
+
+
class MultiThreadedOpenGLGuiHelper : public GUIHelperInterface
{
CommonGraphicsApp* m_app;
b3CriticalSection* m_cs;
+
+
public:
GUIHelperInterface* m_childGuiHelper;
+ int m_uidGenerator;
const unsigned char* m_texels;
int m_textureWidth;
int m_textureHeight;
@@ -300,10 +469,12 @@ public:
int m_textureId;
int m_instanceId;
+
MultiThreadedOpenGLGuiHelper(CommonGraphicsApp* app, GUIHelperInterface* guiHelper)
:m_app(app)
,m_cs(0),
+ m_uidGenerator(0),
m_texels(0),
m_textureId(-1)
{
@@ -466,7 +637,7 @@ public:
virtual CommonRenderInterface* getRenderInterface()
{
- return 0;
+ return m_childGuiHelper->getRenderInterface();
}
virtual CommonGraphicsApp* getAppInterface()
@@ -530,13 +701,113 @@ public:
}
+ btDiscreteDynamicsWorld* m_dynamicsWorld;
+
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
{
+ m_dynamicsWorld = rbWorld;
+ m_cs->lock();
+ m_cs->setSharedParam(1, eGUIHelperAutogenerateGraphicsObjects);
+ m_cs->unlock();
+ while (m_cs->getSharedParam(1) != eGUIHelperIdle)
+ {
+ b3Clock::usleep(1000);
+ }
}
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)
{
}
+
+
+
+
+ btAlignedObjectArray m_userDebugText;
+
+ UserDebugText m_tmpText;
+
+ virtual int addUserDebugText3D( const char* txt, const double positionXYZ[3], const double textColorRGB[3], double size, double lifeTime)
+ {
+
+ m_tmpText.m_itemUniqueId = m_uidGenerator++;
+ m_tmpText.m_lifeTime = lifeTime;
+ m_tmpText.textSize = size;
+ int len = strlen(txt);
+ strcpy(m_tmpText.m_text,txt);
+ m_tmpText.m_textPositionXYZ[0] = positionXYZ[0];
+ m_tmpText.m_textPositionXYZ[1] = positionXYZ[1];
+ m_tmpText.m_textPositionXYZ[2] = positionXYZ[2];
+ m_tmpText.m_textColorRGB[0] = textColorRGB[0];
+ m_tmpText.m_textColorRGB[1] = textColorRGB[1];
+ m_tmpText.m_textColorRGB[2] = textColorRGB[2];
+
+ m_cs->lock();
+ m_cs->setSharedParam(1, eGUIUserDebugAddText);
+ m_cs->unlock();
+ while (m_cs->getSharedParam(1) != eGUIHelperIdle)
+ {
+ b3Clock::usleep(150);
+ }
+
+ return m_userDebugText[m_userDebugText.size()-1].m_itemUniqueId;
+ }
+
+ btAlignedObjectArray m_userDebugLines;
+ UserDebugDrawLine m_tmpLine;
+
+ virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime )
+ {
+ m_tmpLine.m_lifeTime = lifeTime;
+ m_tmpLine.m_lineWidth = lineWidth;
+ m_tmpLine.m_itemUniqueId = m_uidGenerator++;
+ m_tmpLine.m_debugLineFromXYZ[0] = debugLineFromXYZ[0];
+ m_tmpLine.m_debugLineFromXYZ[1] = debugLineFromXYZ[1];
+ m_tmpLine.m_debugLineFromXYZ[2] = debugLineFromXYZ[2];
+
+ m_tmpLine.m_debugLineToXYZ[0] = debugLineToXYZ[0];
+ m_tmpLine.m_debugLineToXYZ[1] = debugLineToXYZ[1];
+ m_tmpLine.m_debugLineToXYZ[2] = debugLineToXYZ[2];
+
+ m_tmpLine.m_debugLineColorRGB[0] = debugLineColorRGB[0];
+ m_tmpLine.m_debugLineColorRGB[1] = debugLineColorRGB[1];
+ m_tmpLine.m_debugLineColorRGB[2] = debugLineColorRGB[2];
+
+ m_cs->lock();
+ m_cs->setSharedParam(1, eGUIUserDebugAddLine);
+ m_cs->unlock();
+ while (m_cs->getSharedParam(1) != eGUIHelperIdle)
+ {
+ b3Clock::usleep(150);
+ }
+ return m_userDebugLines[m_userDebugLines.size()-1].m_itemUniqueId;
+ }
+
+ int m_removeDebugItemUid;
+
+ virtual void removeUserDebugItem( int debugItemUniqueId)
+ {
+ m_removeDebugItemUid = debugItemUniqueId;
+ m_cs->lock();
+ m_cs->setSharedParam(1, eGUIUserDebugRemoveItem);
+ m_cs->unlock();
+ while (m_cs->getSharedParam(1) != eGUIHelperIdle)
+ {
+ b3Clock::usleep(150);
+ }
+
+ }
+ virtual void removeAllUserDebugItems( )
+ {
+ m_cs->lock();
+ m_cs->setSharedParam(1, eGUIUserDebugRemoveAllItems);
+ m_cs->unlock();
+ while (m_cs->getSharedParam(1) != eGUIHelperIdle)
+ {
+ b3Clock::usleep(150);
+ }
+
+ }
+
};
@@ -548,7 +819,9 @@ class PhysicsServerExample : public SharedMemoryCommon
MotionArgs m_args[MAX_MOTION_NUM_THREADS];
MultiThreadedOpenGLGuiHelper* m_multiThreadedHelper;
bool m_wantsShutdown;
-
+#ifdef B3_USE_MIDI
+ RtMidiIn* m_midi;
+#endif
bool m_isConnected;
btClock m_clock;
bool m_replay;
@@ -593,6 +866,7 @@ public:
virtual bool wantsTermination();
virtual bool isConnected();
virtual void renderScene();
+ void drawUserDebugLines();
virtual void exitPhysics();
virtual void physicsDebugDraw(int debugFlags);
@@ -608,8 +882,8 @@ public:
if (m_replay)
return false;
- CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
-
+ CommonRenderInterface* renderer = m_multiThreadedHelper->m_childGuiHelper->getRenderInterface();// m_guiHelper->getRenderInterface();
+
if (!renderer)
{
return false;
@@ -618,7 +892,14 @@ public:
btVector3 rayTo = getRayTo(int(x), int(y));
btVector3 rayFrom;
renderer->getActiveCamera()->getCameraPosition(rayFrom);
- m_physicsServer.movePickedBody(rayFrom,rayTo);
+
+ MyMouseCommand cmd;
+ cmd.m_rayFrom = rayFrom;
+ cmd.m_rayTo = rayTo;
+ cmd.m_type = MyMouseMove;
+ m_args[0].m_cs->lock();
+ m_args[0].m_mouseCommands.push_back(cmd);
+ m_args[0].m_cs->unlock();
return false;
};
@@ -647,7 +928,13 @@ public:
btVector3 rayFrom = camPos;
btVector3 rayTo = getRayTo(int(x),int(y));
- m_physicsServer.pickBody(rayFrom, rayTo);
+ MyMouseCommand cmd;
+ cmd.m_rayFrom = rayFrom;
+ cmd.m_rayTo = rayTo;
+ cmd.m_type = MyMouseButtonDown;
+ m_args[0].m_cs->lock();
+ m_args[0].m_mouseCommands.push_back(cmd);
+ m_args[0].m_cs->unlock();
}
@@ -655,7 +942,14 @@ public:
{
if (button==0)
{
- m_physicsServer.removePickingConstraint();
+ //m_physicsServer.removePickingConstraint();
+ MyMouseCommand cmd;
+ cmd.m_rayFrom.setValue(0,0,0);
+ cmd.m_rayTo.setValue(0, 0, 0);
+ cmd.m_type = MyMouseButtonUp;
+ m_args[0].m_cs->lock();
+ m_args[0].m_mouseCommands.push_back(cmd);
+ m_args[0].m_cs->unlock();
//remove p2p
}
}
@@ -673,6 +967,30 @@ public:
virtual void processCommandLineArgs(int argc, char* argv[])
{
b3CommandLineArgs args(argc,argv);
+ loadCurrentSettingsVR(args);
+ if (args.GetCmdLineArgument("camPosX", gVRTeleportPos1[0]))
+ {
+ printf("camPosX=%f\n", gVRTeleportPos1[0]);
+ }
+
+ if (args.GetCmdLineArgument("camPosY", gVRTeleportPos1[1]))
+ {
+ printf("camPosY=%f\n", gVRTeleportPos1[1]);
+ }
+
+ if (args.GetCmdLineArgument("camPosZ", gVRTeleportPos1[2]))
+ {
+ printf("camPosZ=%f\n", gVRTeleportPos1[2]);
+ }
+
+ float camRotZ = 0.f;
+ if (args.GetCmdLineArgument("camRotZ", camRotZ))
+ {
+ printf("camRotZ = %f\n", camRotZ);
+ btQuaternion ornZ(btVector3(0, 0, 1), camRotZ);
+ gVRTeleportOrn = ornZ;
+ }
+
if (args.CheckCmdLineFlag("robotassets"))
{
gCreateDefaultRobotAssets = true;
@@ -688,6 +1006,40 @@ public:
};
+#ifdef B3_USE_MIDI
+static bool chooseMidiPort(RtMidiIn *rtmidi)
+{
+ /*
+
+ std::cout << "\nWould you like to open a virtual input port? [y/N] ";
+
+ std::string keyHit;
+ std::getline( std::cin, keyHit );
+ if ( keyHit == "y" ) {
+ rtmidi->openVirtualPort();
+ return true;
+ }
+ */
+
+ std::string portName;
+ unsigned int i = 0, nPorts = rtmidi->getPortCount();
+ if (nPorts == 0) {
+ std::cout << "No midi input ports available!" << std::endl;
+ return false;
+ }
+
+ if (nPorts > 0) {
+ std::cout << "\nOpening midi input port " << rtmidi->getPortName() << std::endl;
+ }
+
+ // std::getline( std::cin, keyHit ); // used to clear out stdin
+ rtmidi->openPort(i);
+
+ return true;
+}
+#endif //B3_USE_MIDI
+
+
PhysicsServerExample::PhysicsServerExample(MultiThreadedOpenGLGuiHelper* helper, SharedMemoryInterface* sharedMem, int options)
:SharedMemoryCommon(helper),
m_physicsServer(sharedMem),
@@ -699,6 +1051,14 @@ m_options(options)
,m_tinyVrGui(0)
#endif
{
+#ifdef B3_USE_MIDI
+ m_midi = new RtMidiIn();
+ chooseMidiPort(m_midi);
+ m_midi->setCallback(&midiCallback);
+ // Don't ignore sysex, timing, or active sensing messages.
+ m_midi->ignoreTypes(false, false, false);
+
+#endif
m_multiThreadedHelper = helper;
b3Printf("Started PhysicsServer\n");
}
@@ -707,6 +1067,10 @@ m_options(options)
PhysicsServerExample::~PhysicsServerExample()
{
+#ifdef B3_USE_MIDI
+ delete m_midi;
+ m_midi = 0;
+#endif
#ifdef BT_ENABLE_VR
delete m_tinyVrGui;
#endif
@@ -916,10 +1280,76 @@ void PhysicsServerExample::stepSimulation(float deltaTime)
m_multiThreadedHelper->getCriticalSection()->unlock();
break;
}
+ case eGUIHelperAutogenerateGraphicsObjects:
+ {
+ m_multiThreadedHelper->m_childGuiHelper->autogenerateGraphicsObjects(m_multiThreadedHelper->m_dynamicsWorld);
+ m_multiThreadedHelper->getCriticalSection()->lock();
+ m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
+ m_multiThreadedHelper->getCriticalSection()->unlock();
+ break;
+ }
+
+ case eGUIUserDebugAddText:
+ {
+ m_multiThreadedHelper->m_userDebugText.push_back(m_multiThreadedHelper->m_tmpText);
+ m_multiThreadedHelper->getCriticalSection()->lock();
+ m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
+ m_multiThreadedHelper->getCriticalSection()->unlock();
+ break;
+ }
+ case eGUIUserDebugAddLine:
+ {
+ m_multiThreadedHelper->m_userDebugLines.push_back(m_multiThreadedHelper->m_tmpLine);
+ m_multiThreadedHelper->getCriticalSection()->lock();
+ m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
+ m_multiThreadedHelper->getCriticalSection()->unlock();
+ break;
+ }
+ case eGUIUserDebugRemoveItem:
+ {
+ for (int i=0;im_userDebugLines.size();i++)
+ {
+ if (m_multiThreadedHelper->m_userDebugLines[i].m_itemUniqueId == m_multiThreadedHelper->m_removeDebugItemUid)
+ {
+ m_multiThreadedHelper->m_userDebugLines.swap(i,m_multiThreadedHelper->m_userDebugLines.size()-1);
+ m_multiThreadedHelper->m_userDebugLines.pop_back();
+ break;
+ }
+ }
+
+
+ for (int i=0;im_userDebugText.size();i++)
+ {
+ if (m_multiThreadedHelper->m_userDebugText[i].m_itemUniqueId == m_multiThreadedHelper->m_removeDebugItemUid)
+ {
+ m_multiThreadedHelper->m_userDebugText.swap(i,m_multiThreadedHelper->m_userDebugText.size()-1);
+ m_multiThreadedHelper->m_userDebugText.pop_back();
+ break;
+ }
+ }
+
+ m_multiThreadedHelper->getCriticalSection()->lock();
+ m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
+ m_multiThreadedHelper->getCriticalSection()->unlock();
+ break;
+ }
+ case eGUIUserDebugRemoveAllItems:
+ {
+ m_multiThreadedHelper->m_userDebugLines.clear();
+ m_multiThreadedHelper->m_userDebugText.clear();
+ m_multiThreadedHelper->m_uidGenerator = 0;
+ m_multiThreadedHelper->getCriticalSection()->lock();
+ m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
+ m_multiThreadedHelper->getCriticalSection()->unlock();
+ break;
+ }
case eGUIHelperIdle:
+ {
+ break;
+ }
default:
{
-
+ btAssert(0);
}
}
@@ -961,13 +1391,72 @@ extern int gDroppedSimulationSteps;
extern int gNumSteps;
extern double gDtInSec;
extern double gSubStep;
+extern int gHuskyId;
+extern btTransform huskyTr;
+void PhysicsServerExample::drawUserDebugLines()
+{
+ static char line0[1024];
+ static char line1[1024];
+
+ //draw all user-debug-lines
+
+ //add array of lines
+
+ //draw all user- 'text3d' messages
+ if (m_multiThreadedHelper)
+ {
+
+ for (int i = 0; im_userDebugLines.size(); i++)
+ {
+ btVector3 from;
+ from.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[0],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[1],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[2]);
+ btVector3 toX;
+ toX.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[0],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[1],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[2]);
+
+ btVector3 color;
+ color.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[0],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[1],
+ m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[2]);
+
+
+ m_guiHelper->getAppInterface()->m_renderer->drawLine(from, toX, color, m_multiThreadedHelper->m_userDebugLines[i].m_lineWidth);
+ }
+
+ for (int i = 0; im_userDebugText.size(); i++)
+ {
+ m_guiHelper->getAppInterface()->drawText3D(m_multiThreadedHelper->m_userDebugText[i].m_text,
+ m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[0],
+ m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[1],
+ m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[2],
+ m_multiThreadedHelper->m_userDebugText[i].textSize);
+
+ }
+ }
+
+}
+
void PhysicsServerExample::renderScene()
{
+
+#if 0
+ ///little VR test to follow/drive Husky vehicle
+ if (gHuskyId >= 0)
+ {
+ gVRTeleportPos1 = huskyTr.getOrigin();
+ gVRTeleportOrn = huskyTr.getRotation();
+ }
+#endif
+
+
B3_PROFILE("PhysicsServerExample::RenderScene");
- static char line0[1024];
- static char line1[1024];
+
+ drawUserDebugLines();
if (gEnableRealTimeSimVR)
{
@@ -981,6 +1470,7 @@ void PhysicsServerExample::renderScene()
static int count = 0;
count++;
+#if 0
if (0 == (count & 1))
{
btScalar curTime = m_clock.getTimeSeconds();
@@ -1001,6 +1491,7 @@ void PhysicsServerExample::renderScene()
worseFps = 1000000;
}
}
+#endif
#ifdef BT_ENABLE_VR
if ((gInternalSimFlags&2 ) && m_tinyVrGui==0)
@@ -1025,7 +1516,9 @@ void PhysicsServerExample::renderScene()
tr = tr*b3Transform(b3Quaternion(0,0,-SIMD_HALF_PI),b3MakeVector3(0,0,0));
b3Scalar dt = 0.01;
m_tinyVrGui->clearTextArea();
-
+ static char line0[1024];
+ static char line1[1024];
+
m_tinyVrGui->grapicalPrintf(line0,0,0,0,0,0,255);
m_tinyVrGui->grapicalPrintf(line1,0,16,255,255,255,255);
@@ -1037,9 +1530,27 @@ void PhysicsServerExample::renderScene()
//m_args[0].m_cs->lock();
//gVRTeleportPos[0] += 0.01;
- vrOffset[12]=-gVRTeleportPos[0];
- vrOffset[13]=-gVRTeleportPos[1];
- vrOffset[14]=-gVRTeleportPos[2];
+ btTransform tr2a, tr2;
+ tr2a.setIdentity();
+ tr2.setIdentity();
+ tr2.setOrigin(gVRTeleportPos1);
+ tr2a.setRotation(gVRTeleportOrn);
+ btTransform trTotal = tr2*tr2a;
+ btTransform trInv = trTotal.inverse();
+
+ btMatrix3x3 vrOffsetRot;
+ vrOffsetRot.setRotation(trInv.getRotation());
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ vrOffset[i + 4 * j] = vrOffsetRot[i][j];
+ }
+ }
+
+ vrOffset[12]= trInv.getOrigin()[0];
+ vrOffset[13]= trInv.getOrigin()[1];
+ vrOffset[14]= trInv.getOrigin()[2];
this->m_multiThreadedHelper->m_childGuiHelper->getRenderInterface()->
getActiveCamera()->setVRCameraOffsetTransform(vrOffset);
@@ -1073,62 +1584,22 @@ void PhysicsServerExample::renderScene()
if (m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->isVRCamera())
{
- gEnableRealTimeSimVR = true;
- }
-
- if (gDebugRenderToggle)
- if (m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->isVRCamera())
- {
-
- B3_PROFILE("Draw Debug HUD");
- //some little experiment to add text/HUD to a VR camera (HTC Vive/Oculus Rift)
-
-
- float pos[4];
- m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->getCameraTargetPosition(pos);
- pos[0]+=gVRTeleportPos[0];
- pos[1]+=gVRTeleportPos[1];
- pos[2]+=gVRTeleportPos[2];
-
- btTransform viewTr;
- btScalar m[16];
- float mf[16];
- m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->getCameraViewMatrix(mf);
- for (int i=0;i<16;i++)
+ if (!gEnableRealTimeSimVR)
{
- m[i] = mf[i];
+ gEnableRealTimeSimVR = true;
+ m_physicsServer.enableRealTimeSimulation(1);
}
- m[12]=+gVRTeleportPos[0];
- m[13]=+gVRTeleportPos[1];
- m[14]=+gVRTeleportPos[2];
- viewTr.setFromOpenGLMatrix(m);
- btTransform viewTrInv = viewTr.inverse();
-
- btVector3 side = viewTrInv.getBasis().getColumn(0);
- btVector3 up = viewTrInv.getBasis().getColumn(1);
- btVector3 fwd = viewTrInv.getBasis().getColumn(2);
-
-
- float upMag = 0;
- float sideMag = 2.2;
- float fwdMag = -4;
-
- m_guiHelper->getAppInterface()->drawText3D(line0,pos[0]+upMag*up[0]-sideMag*side[0]+fwdMag*fwd[0],pos[1]+upMag*up[1]-sideMag*side[1]+fwdMag*fwd[1],pos[2]+upMag*up[2]-sideMag*side[2]+fwdMag*fwd[2],1);
- //btVector3 fwd = viewTrInv.getBasis().getColumn(2);
-
- up = viewTrInv.getBasis().getColumn(1);
- upMag = -0.3;
-
-
-
- m_guiHelper->getAppInterface()->drawText3D(line1,pos[0]+upMag*up[0]-sideMag*side[0]+fwdMag*fwd[0],pos[1]+upMag*up[1]-sideMag*side[1]+fwdMag*fwd[1],pos[2]+upMag*up[2]-sideMag*side[2]+fwdMag*fwd[2],1);
}
+
+
//m_args[0].m_cs->unlock();
}
void PhysicsServerExample::physicsDebugDraw(int debugDrawFlags)
{
+ drawUserDebugLines();
+
///debug rendering
m_physicsServer.physicsDebugDraw(debugDrawFlags);
@@ -1238,13 +1709,16 @@ void PhysicsServerExample::vrControllerButtonCallback(int controllerId, int butt
return;
if (gGraspingController < 0)
+ {
gGraspingController = controllerId;
-
+ gEnableKukaControl = true;
+ }
if (controllerId != gGraspingController)
{
if (button == 1 && state == 0)
{
- gVRTeleportPos = gLastPickPos;
+ gResetSimulation = true;
+ //gVRTeleportPos1 = gLastPickPos;
}
} else
{
@@ -1256,7 +1730,7 @@ void PhysicsServerExample::vrControllerButtonCallback(int controllerId, int butt
} else
{
gDebugRenderToggle = 0;
-
+#if 0//it confuses people, make it into a debug option in a VR GUI?
if (simTimeScalingFactor==0)
{
simTimeScalingFactor = 1;
@@ -1271,15 +1745,26 @@ void PhysicsServerExample::vrControllerButtonCallback(int controllerId, int butt
simTimeScalingFactor = 0;
}
}
+#endif
}
} else
{
}
}
+
+
if (button==32 && state==0)
{
- gCreateObjectSimVR = 1;
+
+ if (controllerId == gGraspingController)
+ {
+ gCreateObjectSimVR = 1;
+ }
+ else
+ {
+// gEnableKukaControl = !gEnableKukaControl;
+ }
}
@@ -1300,42 +1785,87 @@ void PhysicsServerExample::vrControllerButtonCallback(int controllerId, int butt
m_args[0].m_isVrControllerPicking[controllerId] = (state != 0);
m_args[0].m_isVrControllerReleasing[controllerId] = (state == 0);
}
+
+ btTransform trLocal;
+ trLocal.setIdentity();
+ trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI)*btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
+
+ btTransform trOrg;
+ trOrg.setIdentity();
+ trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
+ trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
+
+ btTransform tr2a;
+ tr2a.setIdentity();
+ btTransform tr2;
+ tr2.setIdentity();
+
+
+
+ tr2.setOrigin(gVRTeleportPos1);
+ tr2a.setRotation(gVRTeleportOrn);
+
+
+ btTransform trTotal = tr2*tr2a*trOrg*trLocal;
+
if ((button == 33) || (button == 1))
{
- m_args[0].m_vrControllerPos[controllerId].setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
- m_args[0].m_vrControllerOrn[controllerId].setValue(orn[0], orn[1], orn[2], orn[3]);
+// m_args[0].m_vrControllerPos[controllerId].setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
+ // m_args[0].m_vrControllerOrn[controllerId].setValue(orn[0], orn[1], orn[2], orn[3]);
+ m_args[0].m_vrControllerPos[controllerId] = trTotal.getOrigin();
+ m_args[0].m_vrControllerOrn[controllerId] = trTotal.getRotation();
}
+
}
}
-
void PhysicsServerExample::vrControllerMoveCallback(int controllerId, float pos[4], float orn[4], float analogAxis)
{
- gEnableRealTimeSimVR = true;
-
if (controllerId <= 0 || controllerId >= MAX_VR_CONTROLLERS)
{
printf("Controller Id exceeds max: %d > %d", controllerId, MAX_VR_CONTROLLERS);
return;
}
+
+ btTransform trLocal;
+ trLocal.setIdentity();
+ trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI)*btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
+
+ btTransform trOrg;
+ trOrg.setIdentity();
+ trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
+ trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
+
+ btTransform tr2a;
+ tr2a.setIdentity();
+ btTransform tr2;
+ tr2.setIdentity();
+
+
+
+ tr2.setOrigin(gVRTeleportPos1);
+ tr2a.setRotation(gVRTeleportOrn);
+
+
+ btTransform trTotal = tr2*tr2a*trOrg*trLocal;
+
if (controllerId == gGraspingController)
{
gVRGripperAnalog = analogAxis;
- gVRGripperPos.setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
- btQuaternion orgOrn(orn[0], orn[1], orn[2], orn[3]);
- gVRGripperOrn = orgOrn*btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI)*btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI);
+
+ gVRGripperPos = trTotal.getOrigin();
+ gVRGripperOrn = trTotal.getRotation();
}
else
{
gVRGripper2Analog = analogAxis;
- gVRController2Pos.setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
- btQuaternion orgOrn(orn[0], orn[1], orn[2], orn[3]);
- gVRController2Orn = orgOrn*btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI)*btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI);
+ gVRController2Pos = trTotal.getOrigin();
+ gVRController2Orn = trTotal.getRotation();
- m_args[0].m_vrControllerPos[controllerId].setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
- m_args[0].m_vrControllerOrn[controllerId].setValue(orn[0], orn[1], orn[2], orn[3]);
+ m_args[0].m_vrControllerPos[controllerId] = trTotal.getOrigin();
+ m_args[0].m_vrControllerOrn[controllerId] = trTotal.getRotation();
}
}
diff --git a/examples/SharedMemory/PhysicsServerSharedMemory.cpp b/examples/SharedMemory/PhysicsServerSharedMemory.cpp
index 111ac07f5..158bdac6b 100644
--- a/examples/SharedMemory/PhysicsServerSharedMemory.cpp
+++ b/examples/SharedMemory/PhysicsServerSharedMemory.cpp
@@ -241,6 +241,12 @@ void PhysicsServerSharedMemory::stepSimulationRealTime(double dtInSec)
m_data->m_commandProcessor->stepSimulationRealTime(dtInSec);
}
+void PhysicsServerSharedMemory::enableRealTimeSimulation(bool enableRealTimeSim)
+{
+ m_data->m_commandProcessor->enableRealTimeSimulation(enableRealTimeSim);
+}
+
+
void PhysicsServerSharedMemory::processClientCommands()
{
diff --git a/examples/SharedMemory/PhysicsServerSharedMemory.h b/examples/SharedMemory/PhysicsServerSharedMemory.h
index f96e7ca4b..f29e844f2 100644
--- a/examples/SharedMemory/PhysicsServerSharedMemory.h
+++ b/examples/SharedMemory/PhysicsServerSharedMemory.h
@@ -28,9 +28,11 @@ public:
virtual void stepSimulationRealTime(double dtInSec);
+ virtual void enableRealTimeSimulation(bool enableRealTimeSim);
+
//bool supportsJointMotor(class btMultiBody* body, int linkIndex);
- //@todo(erwincoumans) Should we have shared memory commands for picking objects?
+
///The pickBody method will try to pick the first body along a ray, return true if succeeds, false otherwise
virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld);
virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld);
diff --git a/examples/SharedMemory/SharedMemoryCommandProcessor.cpp b/examples/SharedMemory/SharedMemoryCommandProcessor.cpp
new file mode 100644
index 000000000..406b9ae4f
--- /dev/null
+++ b/examples/SharedMemory/SharedMemoryCommandProcessor.cpp
@@ -0,0 +1,216 @@
+#include "SharedMemoryCommandProcessor.h"
+
+#include "PosixSharedMemory.h"
+#include "Win32SharedMemory.h"
+#include "Bullet3Common/b3Logging.h"
+#include "Bullet3Common/b3Scalar.h"
+
+#include "SharedMemoryBlock.h"
+
+
+struct SharedMemoryCommandProcessorInternalData
+{
+ int m_sharedMemoryKey;
+ bool m_isConnected;
+ SharedMemoryInterface* m_sharedMemory;
+ bool m_ownsSharedMemory;
+ bool m_verboseOutput;
+ bool m_waitingForServer;
+ SharedMemoryStatus m_lastServerStatus;
+ SharedMemoryBlock* m_testBlock1;
+
+
+ SharedMemoryCommandProcessorInternalData()
+ :m_sharedMemoryKey(SHARED_MEMORY_KEY),
+ m_isConnected(false),
+ m_sharedMemory(0),
+ m_ownsSharedMemory(false),
+ m_verboseOutput(false),
+ m_waitingForServer(false),
+ m_testBlock1(0)
+ {
+
+ }
+};
+
+SharedMemoryCommandProcessor::SharedMemoryCommandProcessor()
+{
+ m_data = new SharedMemoryCommandProcessorInternalData;
+ m_data->m_sharedMemoryKey = SHARED_MEMORY_KEY;
+#ifdef _WIN32
+ m_data->m_sharedMemory = new Win32SharedMemoryClient();
+#else
+ m_data->m_sharedMemory = new PosixSharedMemory();
+#endif
+ m_data->m_ownsSharedMemory = true;
+
+
+}
+
+SharedMemoryCommandProcessor::~SharedMemoryCommandProcessor()
+{
+ if (m_data->m_isConnected)
+ {
+ disconnect();
+ }
+ if (m_data->m_ownsSharedMemory)
+ {
+ delete m_data->m_sharedMemory;
+ }
+ delete m_data;
+
+}
+
+bool SharedMemoryCommandProcessor::connect()
+{
+
+ if (m_data->m_isConnected)
+ return true;
+
+ bool allowCreation = false;
+ m_data->m_testBlock1 = (SharedMemoryBlock*)m_data->m_sharedMemory->allocateSharedMemory(
+ m_data->m_sharedMemoryKey, SHARED_MEMORY_SIZE, allowCreation);
+
+ if (m_data->m_testBlock1) {
+ if (m_data->m_testBlock1->m_magicId != SHARED_MEMORY_MAGIC_NUMBER) {
+ b3Error("Error: please start server before client\n");
+ m_data->m_sharedMemory->releaseSharedMemory(m_data->m_sharedMemoryKey,
+ SHARED_MEMORY_SIZE);
+ m_data->m_testBlock1 = 0;
+ return false;
+ }
+ else {
+ if (m_data->m_verboseOutput) {
+ b3Printf("Connected to existing shared memory, status OK.\n");
+ }
+ m_data->m_isConnected = true;
+ }
+ }
+ else {
+ b3Error("Cannot connect to shared memory");
+ return false;
+ }
+ return true;
+
+}
+
+void SharedMemoryCommandProcessor::disconnect()
+{
+ if (m_data->m_isConnected && m_data->m_sharedMemory)
+ {
+ m_data->m_sharedMemory->releaseSharedMemory(m_data->m_sharedMemoryKey, SHARED_MEMORY_SIZE);
+ }
+ m_data->m_isConnected = false;
+
+}
+
+bool SharedMemoryCommandProcessor::isConnected() const
+{
+ return m_data->m_isConnected;
+}
+
+
+bool SharedMemoryCommandProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
+{
+ if (!m_data->m_waitingForServer) {
+ if (&m_data->m_testBlock1->m_clientCommands[0] != &clientCmd) {
+ m_data->m_testBlock1->m_clientCommands[0] = clientCmd;
+ }
+ m_data->m_testBlock1->m_numClientCommands++;
+ m_data->m_waitingForServer = true;
+ }
+
+ return false;
+}
+
+bool SharedMemoryCommandProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
+{
+ SharedMemoryStatus* stat = 0;
+
+ m_data->m_lastServerStatus.m_dataStream = 0;
+ m_data->m_lastServerStatus.m_numDataStreamBytes = 0;
+
+ if (!m_data->m_testBlock1)
+ {
+ //m_data->m_lastServerStatus.m_type = CMD_SHARED_MEMORY_NOT_INITIALIZED;
+ //return &m_data->m_lastServerStatus;
+ //serverStatusOut = m_data->m_lastServerStatus;
+ return false;
+ }
+
+ if (!m_data->m_waitingForServer) {
+ return false;
+ }
+
+ if (m_data->m_testBlock1->m_magicId != SHARED_MEMORY_MAGIC_NUMBER)
+ {
+ //m_data->m_lastServerStatus.m_type = CMD_SHARED_MEMORY_NOT_INITIALIZED;
+ //return &m_data->m_lastServerStatus;
+ return false;
+ }
+
+ if (m_data->m_testBlock1->m_numServerCommands >
+ m_data->m_testBlock1->m_numProcessedServerCommands)
+ {
+ b3Assert(m_data->m_testBlock1->m_numServerCommands ==
+ m_data->m_testBlock1->m_numProcessedServerCommands + 1);
+
+ const SharedMemoryStatus& serverCmd = m_data->m_testBlock1->m_serverCommands[0];
+ m_data->m_lastServerStatus = serverCmd;
+ m_data->m_lastServerStatus.m_dataStream = m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor;
+
+ for (int i = 0; i < m_data->m_lastServerStatus.m_numDataStreamBytes; i++)
+ {
+ bufferServerToClient[i] = m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor[i];
+ }
+
+ m_data->m_testBlock1->m_numProcessedServerCommands++;
+ // we don't have more than 1 command outstanding (in total, either server or client)
+ b3Assert(m_data->m_testBlock1->m_numProcessedServerCommands ==
+ m_data->m_testBlock1->m_numServerCommands);
+
+ if (m_data->m_testBlock1->m_numServerCommands ==
+ m_data->m_testBlock1->m_numProcessedServerCommands) {
+ m_data->m_waitingForServer = false;
+ }
+ else {
+ m_data->m_waitingForServer = true;
+ }
+
+ serverStatusOut = m_data->m_lastServerStatus;
+
+ return true;
+ }
+ return false;
+}
+
+void SharedMemoryCommandProcessor::renderScene()
+{
+}
+
+void SharedMemoryCommandProcessor::physicsDebugDraw(int debugDrawFlags)
+{
+}
+
+void SharedMemoryCommandProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper)
+{
+}
+
+void SharedMemoryCommandProcessor::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem)
+{
+ if (m_data->m_sharedMemory && m_data->m_ownsSharedMemory)
+ {
+ delete m_data->m_sharedMemory;
+ }
+ m_data->m_ownsSharedMemory = false;
+ m_data->m_sharedMemory = sharedMem;
+
+}
+
+
+void SharedMemoryCommandProcessor::setSharedMemoryKey(int key)
+{
+ m_data->m_sharedMemoryKey = key;
+}
+
+
diff --git a/examples/SharedMemory/SharedMemoryCommandProcessor.h b/examples/SharedMemory/SharedMemoryCommandProcessor.h
new file mode 100644
index 000000000..bec9e614f
--- /dev/null
+++ b/examples/SharedMemory/SharedMemoryCommandProcessor.h
@@ -0,0 +1,37 @@
+#ifndef SHARED_MEMORY_COMMAND_PROCESSOR_H
+#define SHARED_MEMORY_COMMAND_PROCESSOR_H
+
+#include "PhysicsCommandProcessorInterface.h"
+
+class SharedMemoryCommandProcessor : public PhysicsCommandProcessorInterface
+{
+
+ struct SharedMemoryCommandProcessorInternalData* m_data;
+
+public:
+ SharedMemoryCommandProcessor();
+
+ virtual ~SharedMemoryCommandProcessor();
+
+ virtual bool connect();
+
+ virtual void disconnect();
+
+ virtual bool isConnected() const;
+
+ virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
+
+ virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
+
+ virtual void renderScene();
+ virtual void physicsDebugDraw(int debugDrawFlags);
+ virtual void setGuiHelper(struct GUIHelperInterface* guiHelper);
+
+ void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem);
+ void setSharedMemoryKey(int key);
+
+
+};
+
+#endif //SHARED_MEMORY_COMMAND_PROCESSOR_H
+
diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h
index 8a34189be..d905ca980 100644
--- a/examples/SharedMemory/SharedMemoryCommands.h
+++ b/examples/SharedMemory/SharedMemoryCommands.h
@@ -24,7 +24,7 @@
typedef unsigned long long int smUint64_t;
#endif
-#define SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE (256*1024)
+#define SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE (512*1024)
#define SHARED_MEMORY_SERVER_TEST_C
#define MAX_DEGREE_OF_FREEDOM 128
@@ -67,6 +67,11 @@ struct SdfArgs
int m_useMultiBody;
};
+struct FileArgs
+{
+ char m_fileName[MAX_URDF_FILENAME_LENGTH];
+};
+
enum EnumUrdfArgsUpdateFlags
{
URDF_ARGS_FILE_NAME=1,
@@ -90,7 +95,6 @@ struct UrdfArgs
struct BulletDataStreamArgs
{
char m_bulletFileName[MAX_FILENAME_LENGTH];
- int m_streamChunkLength;
int m_bodyUniqueId;
};
@@ -105,7 +109,9 @@ enum EnumInitPoseFlags
{
INIT_POSE_HAS_INITIAL_POSITION=1,
INIT_POSE_HAS_INITIAL_ORIENTATION=2,
- INIT_POSE_HAS_JOINT_STATE=4
+ INIT_POSE_HAS_JOINT_STATE=4,
+ INIT_POSE_HAS_BASE_LINEAR_VELOCITY = 8,
+ INIT_POSE_HAS_BASE_ANGULAR_VELOCITY = 16,
};
@@ -118,6 +124,8 @@ struct InitPoseArgs
int m_bodyUniqueId;
int m_hasInitialStateQ[MAX_DEGREE_OF_FREEDOM];
double m_initialStateQ[MAX_DEGREE_OF_FREEDOM];
+ int m_hasInitialStateQdot[MAX_DEGREE_OF_FREEDOM];
+ double m_initialStateQdot[MAX_DEGREE_OF_FREEDOM];
};
@@ -134,21 +142,54 @@ struct RequestPixelDataArgs
int m_startPixelIndex;
int m_pixelWidth;
int m_pixelHeight;
+ float m_lightDirection[3];
+ float m_lightColor[3];
+ float m_lightDistance;
+ float m_lightAmbientCoeff;
+ float m_lightDiffuseCoeff;
+ float m_lightSpecularCoeff;
+ int m_hasShadow;
};
enum EnumRequestPixelDataUpdateFlags
{
REQUEST_PIXEL_ARGS_HAS_CAMERA_MATRICES=1,
- REQUEST_PIXEL_ARGS_SET_PIXEL_WIDTH_HEIGHT=4,
+ REQUEST_PIXEL_ARGS_SET_PIXEL_WIDTH_HEIGHT=2,
+ REQUEST_PIXEL_ARGS_SET_LIGHT_DIRECTION=4,
+ REQUEST_PIXEL_ARGS_SET_LIGHT_COLOR=8,
+ REQUEST_PIXEL_ARGS_SET_LIGHT_DISTANCE=16,
+ REQUEST_PIXEL_ARGS_SET_SHADOW=32,
+ REQUEST_PIXEL_ARGS_SET_AMBIENT_COEFF=64,
+ REQUEST_PIXEL_ARGS_SET_DIFFUSE_COEFF=128,
+ REQUEST_PIXEL_ARGS_SET_SPECULAR_COEFF=256,
//don't exceed (1<<15), because this enum is shared with EnumRenderer in SharedMemoryPublic.h
};
+enum EnumRequestContactDataUpdateFlags
+{
+ CMD_REQUEST_CONTACT_POINT_HAS_QUERY_MODE=1,
+ CMD_REQUEST_CONTACT_POINT_HAS_CLOSEST_DISTANCE_THRESHOLD=2,
+ CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_A_FILTER = 4,
+ CMD_REQUEST_CONTACT_POINT_HAS_LINK_INDEX_B_FILTER = 8,
+};
+
struct RequestContactDataArgs
{
int m_startingContactPointIndex;
int m_objectAIndexFilter;
int m_objectBIndexFilter;
+ int m_linkIndexAIndexFilter;
+ int m_linkIndexBIndexFilter;
+ double m_closestDistanceThreshold;
+ int m_mode;
+};
+
+struct RequestOverlappingObjectsArgs
+{
+ int m_startingOverlappingObjectIndex;
+ double m_aabbQueryMin[3];
+ double m_aabbQueryMax[3];
};
struct RequestVisualShapeDataArgs
@@ -252,7 +293,16 @@ enum EnumSimParamUpdateFlags
SIM_PARAM_UPDATE_NUM_SIMULATION_SUB_STEPS=8,
SIM_PARAM_UPDATE_REAL_TIME_SIMULATION = 16,
SIM_PARAM_UPDATE_DEFAULT_CONTACT_ERP=32,
- SIM_PARAM_UPDATE_INTERNAL_SIMULATION_FLAGS=64
+ SIM_PARAM_UPDATE_INTERNAL_SIMULATION_FLAGS=64,
+ SIM_PARAM_UPDATE_USE_SPLIT_IMPULSE=128,
+ SIM_PARAM_UPDATE_SPLIT_IMPULSE_PENETRATION_THRESHOLD = 256,
+};
+
+enum EnumLoadBunnyUpdateFlags
+{
+ LOAD_BUNNY_UPDATE_SCALE=1,
+ LOAD_BUNNY_UPDATE_MASS=2,
+ LOAD_BUNNY_UPDATE_COLLISION_MARGIN=4
};
enum EnumSimParamInternalSimFlags
@@ -270,10 +320,19 @@ struct SendPhysicsSimulationParameters
int m_numSimulationSubSteps;
int m_numSolverIterations;
bool m_allowRealTimeSimulation;
+ int m_useSplitImpulse;
+ double m_splitImpulsePenetrationThreshold;
int m_internalSimFlags;
double m_defaultContactERP;
};
+struct LoadBunnyArgs
+{
+ double m_scale;
+ double m_mass;
+ double m_collisionMargin;
+};
+
struct RequestActualStateArgs
{
int m_bodyUniqueId;
@@ -455,7 +514,14 @@ struct CalculateInverseKinematicsResultArgs
double m_jointPositions[MAX_DEGREE_OF_FREEDOM];
};
-struct CreateJointArgs
+enum EnumUserConstraintFlags
+{
+ USER_CONSTRAINT_ADD_CONSTRAINT=1,
+ USER_CONSTRAINT_REMOVE_CONSTRAINT=2,
+ USER_CONSTRAINT_CHANGE_CONSTRAINT=4
+};
+
+struct UserConstraintArgs
{
int m_parentBodyIndex;
int m_parentJointIndex;
@@ -465,8 +531,53 @@ struct CreateJointArgs
double m_childFrame[7];
double m_jointAxis[3];
int m_jointType;
+ int m_userConstraintUniqueId;
};
+struct UserConstraintResultArgs
+{
+ int m_userConstraintUniqueId;
+};
+
+enum EnumUserDebugDrawFlags
+{
+ USER_DEBUG_HAS_LINE=1,
+ USER_DEBUG_HAS_TEXT=2,
+ USER_DEBUG_REMOVE_ONE_ITEM=4,
+ USER_DEBUG_REMOVE_ALL=8,
+ USER_DEBUG_SET_CUSTOM_OBJECT_COLOR = 16,
+ USER_DEBUG_REMOVE_CUSTOM_OBJECT_COLOR = 32,
+
+};
+
+struct UserDebugDrawArgs
+{
+ double m_debugLineFromXYZ[3];
+ double m_debugLineToXYZ[3];
+ double m_debugLineColorRGB[3];
+ double m_lineWidth;
+
+ double m_lifeTime;
+ int m_removeItemUniqueId;
+
+ char m_text[MAX_FILENAME_LENGTH];
+ double m_textPositionXYZ[3];
+ double m_textColorRGB[3];
+ double m_textSize;
+
+ double m_objectDebugColorRGB[3];
+ int m_objectUniqueId;
+ int m_linkIndex;
+};
+
+
+
+struct UserDebugDrawResultArgs
+{
+ int m_debugItemUniqueId;
+};
+
+
struct SharedMemoryCommand
{
int m_type;
@@ -481,6 +592,7 @@ struct SharedMemoryCommand
{
struct UrdfArgs m_urdfArguments;
struct SdfArgs m_sdfArguments;
+ struct FileArgs m_fileArguments;
struct SdfRequestInfoArgs m_sdfRequestInfoArgs;
struct InitPoseArgs m_initPoseArgs;
struct SendPhysicsSimulationParameters m_physSimParamArgs;
@@ -495,12 +607,15 @@ struct SharedMemoryCommand
struct ExternalForceArgs m_externalForceArguments;
struct CalculateInverseDynamicsArgs m_calculateInverseDynamicsArguments;
struct CalculateJacobianArgs m_calculateJacobianArguments;
- struct CreateJointArgs m_createJointArguments;
+ struct UserConstraintArgs m_userConstraintArguments;
struct RequestContactDataArgs m_requestContactPointArguments;
+ struct RequestOverlappingObjectsArgs m_requestOverlappingObjectsArgs;
struct RequestVisualShapeDataArgs m_requestVisualShapeDataArguments;
struct UpdateVisualShapeDataArgs m_updateVisualShapeDataArguments;
struct LoadTextureArgs m_loadTextureArguments;
struct CalculateInverseKinematicsArgs m_calculateInverseKinematicsArguments;
+ struct UserDebugDrawArgs m_userDebugDrawArgs;
+ struct LoadBunnyArgs m_loadBunnyArguments;
};
};
@@ -516,6 +631,13 @@ struct SendContactDataArgs
int m_numRemainingContactPoints;
};
+struct SendOverlappingObjectsArgs
+{
+ int m_startingOverlappingObjectIndex;
+ int m_numOverlappingObjectsCopied;
+ int m_numRemainingOverlappingObjects;
+};
+
struct SharedMemoryStatus
{
int m_type;
@@ -523,6 +645,10 @@ struct SharedMemoryStatus
smUint64_t m_timeStamp;
int m_sequenceNumber;
+ //m_streamBytes is only for internal purposes
+ int m_numDataStreamBytes;
+ char* m_dataStream;
+
union
{
struct BulletDataStreamArgs m_dataStreamArguments;
@@ -534,8 +660,11 @@ struct SharedMemoryStatus
struct CalculateInverseDynamicsResultArgs m_inverseDynamicsResultArgs;
struct CalculateJacobianResultArgs m_jacobianResultArgs;
struct SendContactDataArgs m_sendContactPointArgs;
+ struct SendOverlappingObjectsArgs m_sendOverlappingObjectsArgs;
struct CalculateInverseKinematicsResultArgs m_inverseKinematicsResultArgs;
struct SendVisualShapeDataArgs m_sendVisualShapeArgs;
+ struct UserDebugDrawResultArgs m_userDebugDrawArgs;
+ struct UserConstraintResultArgs m_userConstraintResultArgs;
};
};
diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h
index b435a38a5..fe79d9dcb 100644
--- a/examples/SharedMemory/SharedMemoryPublic.h
+++ b/examples/SharedMemory/SharedMemoryPublic.h
@@ -7,20 +7,22 @@ enum EnumSharedMemoryClientCommand
{
CMD_LOAD_SDF,
CMD_LOAD_URDF,
+ CMD_LOAD_BULLET,
+ CMD_SAVE_BULLET,
+ CMD_LOAD_MJCF,
CMD_LOAD_BUNNY,
- CMD_SEND_BULLET_DATA_STREAM,
- CMD_CREATE_BOX_COLLISION_SHAPE,
-// CMD_DELETE_BOX_COLLISION_SHAPE,
- CMD_CREATE_RIGID_BODY,
- CMD_DELETE_RIGID_BODY,
- CMD_CREATE_SENSOR,///enable or disable joint feedback for force/torque sensors
-// CMD_REQUEST_SENSOR_MEASUREMENTS,//see CMD_REQUEST_ACTUAL_STATE/CMD_ACTUAL_STATE_UPDATE_COMPLETED
- CMD_INIT_POSE,
- CMD_SEND_PHYSICS_SIMULATION_PARAMETERS,
- CMD_SEND_DESIRED_STATE,//todo: reconsider naming, for example SET_JOINT_CONTROL_VARIABLE?
- CMD_REQUEST_ACTUAL_STATE,
- CMD_REQUEST_DEBUG_LINES,
+ CMD_SEND_BULLET_DATA_STREAM,
+ CMD_CREATE_BOX_COLLISION_SHAPE,
+ CMD_CREATE_RIGID_BODY,
+ CMD_DELETE_RIGID_BODY,
+ CMD_CREATE_SENSOR,///enable or disable joint feedback for force/torque sensors
+ CMD_INIT_POSE,
+ CMD_SEND_PHYSICS_SIMULATION_PARAMETERS,
+ CMD_SEND_DESIRED_STATE,//todo: reconsider naming, for example SET_JOINT_CONTROL_VARIABLE?
+ CMD_REQUEST_ACTUAL_STATE,
+ CMD_REQUEST_DEBUG_LINES,
CMD_REQUEST_BODY_INFO,
+ CMD_REQUEST_INTERNAL_DATA,
CMD_STEP_FORWARD_SIMULATION,
CMD_RESET_SIMULATION,
CMD_PICK_BODY,
@@ -31,12 +33,16 @@ enum EnumSharedMemoryClientCommand
CMD_CALCULATE_INVERSE_DYNAMICS,
CMD_CALCULATE_INVERSE_KINEMATICS,
CMD_CALCULATE_JACOBIAN,
- CMD_CREATE_JOINT,
+ CMD_USER_CONSTRAINT,
CMD_REQUEST_CONTACT_POINT_INFORMATION,
+ CMD_REQUEST_AABB_OVERLAP,
CMD_SAVE_WORLD,
CMD_REQUEST_VISUAL_SHAPE_INFO,
CMD_UPDATE_VISUAL_SHAPE,
CMD_LOAD_TEXTURE,
+ CMD_SET_SHADOW,
+ CMD_USER_DEBUG_DRAW,
+
//don't go beyond this command!
CMD_MAX_CLIENT_COMMANDS,
@@ -54,6 +60,14 @@ enum EnumSharedMemoryServerStatus
CMD_SDF_LOADING_FAILED,
CMD_URDF_LOADING_COMPLETED,
CMD_URDF_LOADING_FAILED,
+ CMD_BULLET_LOADING_COMPLETED,
+ CMD_BULLET_LOADING_FAILED,
+ CMD_BULLET_SAVING_COMPLETED,
+ CMD_BULLET_SAVING_FAILED,
+ CMD_MJCF_LOADING_COMPLETED,
+ CMD_MJCF_LOADING_FAILED,
+ CMD_REQUEST_INTERNAL_DATA_COMPLETED,
+ CMD_REQUEST_INTERNAL_DATA_FAILED,
CMD_BULLET_DATA_STREAM_RECEIVED_COMPLETED,
CMD_BULLET_DATA_STREAM_RECEIVED_FAILED,
CMD_BOX_COLLISION_SHAPE_CREATION_COMPLETED,
@@ -77,6 +91,8 @@ enum EnumSharedMemoryServerStatus
CMD_CALCULATED_JACOBIAN_FAILED,
CMD_CONTACT_POINT_INFORMATION_COMPLETED,
CMD_CONTACT_POINT_INFORMATION_FAILED,
+ CMD_REQUEST_AABB_OVERLAP_COMPLETED,
+ CMD_REQUEST_AABB_OVERLAP_FAILED,
CMD_CALCULATE_INVERSE_KINEMATICS_COMPLETED,
CMD_CALCULATE_INVERSE_KINEMATICS_FAILED,
CMD_SAVE_WORLD_COMPLETED,
@@ -87,6 +103,10 @@ enum EnumSharedMemoryServerStatus
CMD_VISUAL_SHAPE_UPDATE_FAILED,
CMD_LOAD_TEXTURE_COMPLETED,
CMD_LOAD_TEXTURE_FAILED,
+ CMD_USER_DEBUG_DRAW_COMPLETED,
+ CMD_USER_DEBUG_DRAW_FAILED,
+ CMD_USER_CONSTRAINT_COMPLETED,
+ CMD_USER_CONSTRAINT_FAILED,
//don't go beyond 'CMD_MAX_SERVER_COMMANDS!
CMD_MAX_SERVER_COMMANDS
};
@@ -110,10 +130,12 @@ enum
// copied from btMultiBodyLink.h
enum JointType {
- eRevoluteType = 0,
- ePrismaticType = 1,
- eFixedType = 2,
- ePoint2PointType = 3,
+ eRevoluteType = 0,
+ ePrismaticType = 1,
+ eSphericalType = 2,
+ ePlanarType = 3,
+ eFixedType = 4,
+ ePoint2PointType = 5,
};
struct b3JointInfo
@@ -155,6 +177,18 @@ struct b3DebugLines
const float* m_linesColor;//float red,green,blue times 'm_numDebugLines'.
};
+struct b3OverlappingObject
+{
+ int m_objectUniqueId;
+ int m_linkIndex;
+};
+
+struct b3AABBOverlapData
+{
+ int m_numOverlappingObjects;
+ struct b3OverlappingObject* m_overlappingObjects;
+};
+
struct b3CameraImageData
{
int m_pixelWidth;
@@ -189,6 +223,13 @@ struct b3ContactPointData
// double m_angularFrictionForce;
};
+enum
+{
+ CONTACT_QUERY_MODE_REPORT_EXISTING_CONTACT_POINTS = 0,
+ CONTACT_QUERY_MODE_COMPUTE_CLOSEST_POINTS = 1,
+};
+
+
struct b3ContactInformation
{
@@ -207,6 +248,7 @@ struct b3VisualShapeData
char m_meshAssetFileName[VISUAL_SHAPE_MAX_PATH_LEN];
double m_localInertiaFrame[7];//pos[3], orn[4]
//todo: add more data if necessary (material color etc, although material can be in asset file .obj file)
+ double m_rgbaColor[4];
};
struct b3VisualShapeInformation
diff --git a/examples/SharedMemory/TinyRendererVisualShapeConverter.cpp b/examples/SharedMemory/TinyRendererVisualShapeConverter.cpp
index 9bf123413..830e629e8 100644
--- a/examples/SharedMemory/TinyRendererVisualShapeConverter.cpp
+++ b/examples/SharedMemory/TinyRendererVisualShapeConverter.cpp
@@ -36,7 +36,6 @@ subject to the following restrictions:
#include "../TinyRenderer/model.h"
#include "../ThirdPartyLibs/stb_image/stb_image.h"
-
enum MyFileType
{
MY_FILE_STL=1,
@@ -72,17 +71,35 @@ struct TinyRendererVisualShapeConverterInternalData
TGAImage m_rgbColorBuffer;
b3AlignedObjectArray m_textures;
b3AlignedObjectArray m_depthBuffer;
+ b3AlignedObjectArray m_shadowBuffer;
b3AlignedObjectArray m_segmentationMaskBuffer;
-
+ btVector3 m_lightDirection;
+ bool m_hasLightDirection;
+ btVector3 m_lightColor;
+ bool m_hasLightColor;
+ float m_lightDistance;
+ bool m_hasLightDistance;
+ float m_lightAmbientCoeff;
+ bool m_hasLightAmbientCoeff;
+ float m_lightDiffuseCoeff;
+ bool m_hasLightDiffuseCoeff;
+ float m_lightSpecularCoeff;
+ bool m_hasLightSpecularCoeff;
+ bool m_hasShadow;
SimpleCamera m_camera;
+
TinyRendererVisualShapeConverterInternalData()
:m_upAxis(2),
m_swWidth(START_WIDTH),
m_swHeight(START_HEIGHT),
- m_rgbColorBuffer(START_WIDTH,START_HEIGHT,TGAImage::RGB)
+ m_rgbColorBuffer(START_WIDTH,START_HEIGHT,TGAImage::RGB),
+ m_hasLightDirection(false),
+ m_hasLightColor(false),
+ m_hasShadow(false)
{
m_depthBuffer.resize(m_swWidth*m_swHeight);
+ m_shadowBuffer.resize(m_swWidth*m_swHeight);
m_segmentationMaskBuffer.resize(m_swWidth*m_swHeight,-1);
}
@@ -108,8 +125,46 @@ TinyRendererVisualShapeConverter::~TinyRendererVisualShapeConverter()
delete m_data;
}
+void TinyRendererVisualShapeConverter::setLightDirection(float x, float y, float z)
+{
+ m_data->m_lightDirection.setValue(x, y, z);
+ m_data->m_hasLightDirection = true;
+}
+void TinyRendererVisualShapeConverter::setLightColor(float x, float y, float z)
+{
+ m_data->m_lightColor.setValue(x, y, z);
+ m_data->m_hasLightColor = true;
+}
+void TinyRendererVisualShapeConverter::setLightDistance(float dist)
+{
+ m_data->m_lightDistance = dist;
+ m_data->m_hasLightDistance = true;
+}
+
+void TinyRendererVisualShapeConverter::setShadow(bool hasShadow)
+{
+ m_data->m_hasShadow = hasShadow;
+}
+
+void TinyRendererVisualShapeConverter::setLightAmbientCoeff(float ambientCoeff)
+{
+ m_data->m_lightAmbientCoeff = ambientCoeff;
+ m_data->m_hasLightAmbientCoeff = true;
+}
+
+void TinyRendererVisualShapeConverter::setLightDiffuseCoeff(float diffuseCoeff)
+{
+ m_data->m_lightDiffuseCoeff = diffuseCoeff;
+ m_data->m_hasLightDiffuseCoeff = true;
+}
+
+void TinyRendererVisualShapeConverter::setLightSpecularCoeff(float specularCoeff)
+{
+ m_data->m_lightSpecularCoeff = specularCoeff;
+ m_data->m_hasLightSpecularCoeff = true;
+}
void convertURDFToVisualShape(const UrdfVisual* visual, const char* urdfPathPrefix, const btTransform& visualTransform, btAlignedObjectArray& verticesOut, btAlignedObjectArray& indicesOut, btAlignedObjectArray& texturesOut, b3VisualShapeData& visualShapeOut)
{
@@ -527,13 +582,17 @@ void TinyRendererVisualShapeConverter::convertVisualShapes(int linkIndex, const
visualShape.m_localInertiaFrame[4] = localInertiaFrame.getRotation()[1];
visualShape.m_localInertiaFrame[5] = localInertiaFrame.getRotation()[2];
visualShape.m_localInertiaFrame[6] = localInertiaFrame.getRotation()[3];
-
+ visualShape.m_rgbaColor[0] = rgbaColor[0];
+ visualShape.m_rgbaColor[1] = rgbaColor[1];
+ visualShape.m_rgbaColor[2] = rgbaColor[2];
+ visualShape.m_rgbaColor[3] = rgbaColor[3];
+
convertURDFToVisualShape(&vis, pathPrefix, localInertiaFrame.inverse()*childTrans, vertices, indices,textures, visualShape);
m_data->m_visualShapes.push_back(visualShape);
if (vertices.size() && indices.size())
{
- TinyRenderObjectData* tinyObj = new TinyRenderObjectData(m_data->m_rgbColorBuffer,m_data->m_depthBuffer, &m_data->m_segmentationMaskBuffer, bodyUniqueId);
+ TinyRenderObjectData* tinyObj = new TinyRenderObjectData(m_data->m_rgbColorBuffer,m_data->m_depthBuffer, &m_data->m_shadowBuffer, &m_data->m_segmentationMaskBuffer, bodyUniqueId);
unsigned char* textureImage=0;
int textureWidth=0;
int textureHeight=0;
@@ -639,6 +698,7 @@ void TinyRendererVisualShapeConverter::clearBuffers(TGAColor& clearColor)
{
m_data->m_rgbColorBuffer.set(x,y,clearColor);
m_data->m_depthBuffer[x+y*m_data->m_swWidth] = -1e30f;
+ m_data->m_shadowBuffer[x+y*m_data->m_swWidth] = -1e30f;
m_data->m_segmentationMaskBuffer[x+y*m_data->m_swWidth] = -1;
}
}
@@ -673,28 +733,110 @@ void TinyRendererVisualShapeConverter::render(const float viewMat[16], const flo
btVector3 lightDirWorld(-5,200,-40);
- switch (m_data->m_upAxis)
- {
- case 1:
- lightDirWorld = btVector3(-50.f,100,30);
- break;
- case 2:
- lightDirWorld = btVector3(-50.f,30,100);
- break;
- default:{}
- };
+ if (m_data->m_hasLightDirection)
+ {
+ lightDirWorld = m_data->m_lightDirection;
+ }
+ else
+ {
+ switch (m_data->m_upAxis)
+ {
+ case 1:
+ lightDirWorld = btVector3(-50.f, 100, 30);
+ break;
+ case 2:
+ lightDirWorld = btVector3(-50.f, 30, 100);
+ break;
+ default: {}
+ };
+ }
lightDirWorld.normalize();
- // printf("num m_swRenderInstances = %d\n", m_data->m_swRenderInstances.size());
- for (int i=0;im_swRenderInstances.size();i++)
+ btVector3 lightColor(1.0,1.0,1.0);
+ if (m_data->m_hasLightColor)
{
- TinyRendererObjectArray** visualArrayPtr = m_data->m_swRenderInstances.getAtIndex(i);
+ lightColor = m_data->m_lightColor;
+ }
+
+ float lightDistance = 2.0;
+ if (m_data->m_hasLightDistance)
+ {
+ lightDistance = m_data->m_lightDistance;
+ }
+
+ float lightAmbientCoeff = 0.6;
+ if (m_data->m_hasLightAmbientCoeff)
+ {
+ lightAmbientCoeff = m_data->m_lightAmbientCoeff;
+ }
+
+ float lightDiffuseCoeff = 0.35;
+ if (m_data->m_hasLightDiffuseCoeff)
+ {
+ lightDiffuseCoeff = m_data->m_lightDiffuseCoeff;
+ }
+
+ float lightSpecularCoeff = 0.05;
+ if (m_data->m_hasLightSpecularCoeff)
+ {
+ lightSpecularCoeff = m_data->m_lightSpecularCoeff;
+ }
+
+ if (m_data->m_hasShadow)
+ {
+ for (int n=0;nm_swRenderInstances.size();n++)
+ {
+ TinyRendererObjectArray** visualArrayPtr = m_data->m_swRenderInstances.getAtIndex(n);
+ if (0==visualArrayPtr)
+ continue;//can this ever happen?
+ TinyRendererObjectArray* visualArray = *visualArrayPtr;
+
+ btHashPtr colObjHash = m_data->m_swRenderInstances.getKeyAtIndex(n);
+
+
+ const btCollisionObject* colObj = (btCollisionObject*) colObjHash.getPointer();
+
+ for (int v=0;vm_renderObjects.size();v++)
+ {
+
+ TinyRenderObjectData* renderObj = visualArray->m_renderObjects[v];
+
+
+ //sync the object transform
+ const btTransform& tr = colObj->getWorldTransform();
+ tr.getOpenGLMatrix(modelMat);
+
+ for (int i=0;i<4;i++)
+ {
+ for (int j=0;j<4;j++)
+ {
+
+ renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
+ renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
+ renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
+ }
+ }
+ renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
+ renderObj->m_lightDirWorld = lightDirWorld;
+ renderObj->m_lightColor = lightColor;
+ renderObj->m_lightDistance = lightDistance;
+ renderObj->m_lightAmbientCoeff = lightAmbientCoeff;
+ renderObj->m_lightDiffuseCoeff = lightDiffuseCoeff;
+ renderObj->m_lightSpecularCoeff = lightSpecularCoeff;
+ TinyRenderer::renderObjectDepth(*renderObj);
+ }
+ }
+ }
+
+ for (int n=0;nm_swRenderInstances.size();n++)
+ {
+ TinyRendererObjectArray** visualArrayPtr = m_data->m_swRenderInstances.getAtIndex(n);
if (0==visualArrayPtr)
continue;//can this ever happen?
TinyRendererObjectArray* visualArray = *visualArrayPtr;
-
- btHashPtr colObjHash = m_data->m_swRenderInstances.getKeyAtIndex(i);
+
+ btHashPtr colObjHash = m_data->m_swRenderInstances.getKeyAtIndex(n);
const btCollisionObject* colObj = (btCollisionObject*) colObjHash.getPointer();
@@ -704,11 +846,11 @@ void TinyRendererVisualShapeConverter::render(const float viewMat[16], const flo
TinyRenderObjectData* renderObj = visualArray->m_renderObjects[v];
-
+
//sync the object transform
const btTransform& tr = colObj->getWorldTransform();
tr.getOpenGLMatrix(modelMat);
-
+
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
@@ -717,10 +859,15 @@ void TinyRendererVisualShapeConverter::render(const float viewMat[16], const flo
renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
- renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
- renderObj->m_lightDirWorld = lightDirWorld;
}
}
+ renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
+ renderObj->m_lightDirWorld = lightDirWorld;
+ renderObj->m_lightColor = lightColor;
+ renderObj->m_lightDistance = lightDistance;
+ renderObj->m_lightAmbientCoeff = lightAmbientCoeff;
+ renderObj->m_lightDiffuseCoeff = lightDiffuseCoeff;
+ renderObj->m_lightSpecularCoeff = lightSpecularCoeff;
TinyRenderer::renderObject(*renderObj);
}
}
@@ -739,6 +886,7 @@ void TinyRendererVisualShapeConverter::render(const float viewMat[16], const flo
for (int i=0;im_swWidth;i++)
{
btSwap(m_data->m_depthBuffer[l1+i],m_data->m_depthBuffer[l2+i]);
+ btSwap(m_data->m_shadowBuffer[l1+i],m_data->m_shadowBuffer[l2+i]);
btSwap(m_data->m_segmentationMaskBuffer[l1+i],m_data->m_segmentationMaskBuffer[l2+i]);
}
}
@@ -758,6 +906,7 @@ void TinyRendererVisualShapeConverter::setWidthAndHeight(int width, int height)
m_data->m_swHeight = height;
m_data->m_depthBuffer.resize(m_data->m_swWidth*m_data->m_swHeight);
+ m_data->m_shadowBuffer.resize(m_data->m_swWidth*m_data->m_swHeight);
m_data->m_segmentationMaskBuffer.resize(m_data->m_swWidth*m_data->m_swHeight);
m_data->m_rgbColorBuffer = TGAImage(width, height, TGAImage::RGB);
@@ -872,10 +1021,14 @@ int TinyRendererVisualShapeConverter::registerTexture(unsigned char* texels, int
return m_data->m_textures.size()-1;
}
-void TinyRendererVisualShapeConverter::loadTextureFile(const char* filename)
+int TinyRendererVisualShapeConverter::loadTextureFile(const char* filename)
{
int width,height,n;
unsigned char* image=0;
image = stbi_load(filename, &width, &height, &n, 3);
- registerTexture(image, width, height);
-}
\ No newline at end of file
+ if (image && (width>=0) && (height>=0))
+ {
+ return registerTexture(image, width, height);
+ }
+ return -1;
+}
diff --git a/examples/SharedMemory/TinyRendererVisualShapeConverter.h b/examples/SharedMemory/TinyRendererVisualShapeConverter.h
index afd0a2ae6..78b4c62d6 100644
--- a/examples/SharedMemory/TinyRendererVisualShapeConverter.h
+++ b/examples/SharedMemory/TinyRendererVisualShapeConverter.h
@@ -32,13 +32,20 @@ struct TinyRendererVisualShapeConverter : public LinkVisualShapesConverter
void getWidthAndHeight(int& width, int& height);
void setWidthAndHeight(int width, int height);
-
+ void setLightDirection(float x, float y, float z);
+ void setLightColor(float x, float y, float z);
+ void setLightDistance(float dist);
+ void setLightAmbientCoeff(float ambientCoeff);
+ void setLightDiffuseCoeff(float diffuseCoeff);
+ void setLightSpecularCoeff(float specularCoeff);
+ void setShadow(bool hasShadow);
+
void copyCameraImageData(unsigned char* pixelsRGBA, int rgbaBufferSizeInPixels, float* depthBuffer, int depthBufferSizeInPixels,int* segmentationMaskBuffer, int segmentationMaskSizeInPixels, int startPixelIndex, int* widthPtr, int* heightPtr, int* numPixelsCopied);
void render();
void render(const float viewMat[16], const float projMat[16]);
- void loadTextureFile(const char* filename);
+ int loadTextureFile(const char* filename);
int registerTexture(unsigned char* texels, int width, int height);
void activateShapeTexture(int shapeUniqueId, int textureUniqueId);
void activateShapeTexture(int objectUniqueId, int jointIndex, int shapeIndex, int textureUniqueId);
diff --git a/examples/SharedMemory/premake4.lua b/examples/SharedMemory/premake4.lua
index 2215cfbe0..a17afb1f8 100644
--- a/examples/SharedMemory/premake4.lua
+++ b/examples/SharedMemory/premake4.lua
@@ -42,6 +42,14 @@ myfiles =
"PhysicsLoopBack.h",
"PhysicsLoopBackC_API.cpp",
"PhysicsLoopBackC_API.h",
+ "PhysicsClientSharedMemory_C_API.cpp",
+ "PhysicsClientSharedMemory_C_API.h",
+ "PhysicsClientSharedMemory2_C_API.cpp",
+ "PhysicsClientSharedMemory2_C_API.h",
+ "PhysicsClientSharedMemory2.cpp",
+ "PhysicsClientSharedMemory2.h",
+ "SharedMemoryCommandProcessor.cpp",
+ "SharedMemoryCommandProcessor.h",
"PhysicsServerCommandProcessor.cpp",
"PhysicsServerCommandProcessor.h",
"TinyRendererVisualShapeConverter.cpp",
@@ -146,6 +154,37 @@ links {
language "C++"
+ if _OPTIONS["midi"] then
+
+ defines {"B3_USE_MIDI"}
+
+
+
+ includedirs{"../ThirdPartyLibs/midi"}
+
+ files {
+ "../ThirdPartyLibs/midi/RtMidi.cpp",
+ "../ThirdPartyLibs/midi/RtMidi.h",
+ "../ThirdPartyLibs/midi/RtError.h",
+ }
+ if os.is("Windows") then
+ links {"winmm"}
+ defines {"__WINDOWS_MM__", "WIN32"}
+ end
+
+ if os.is("Linux") then
+ defines {"__LINUX_ALSA__"}
+ links {"asound","pthread"}
+ end
+
+ if os.is("MacOSX") then
+ links{"CoreAudio.framework", "coreMIDI.framework", "Cocoa.framework"}
+ defines {"__MACOSX_CORE__"}
+ end
+
+ end
+
+
files {
myfiles,
"../StandaloneMain/main_opengl_single_example.cpp",
@@ -205,7 +244,37 @@ if os.is("Windows") then
else
kind "ConsoleApp"
end
+
+ if _OPTIONS["midi"] then
+ defines {"B3_USE_MIDI"}
+
+
+
+ includedirs{"../ThirdPartyLibs/midi"}
+
+ files {
+ "../ThirdPartyLibs/midi/RtMidi.cpp",
+ "../ThirdPartyLibs/midi/RtMidi.h",
+ "../ThirdPartyLibs/midi/RtError.h",
+ }
+ if os.is("Windows") then
+ links {"winmm"}
+ defines {"__WINDOWS_MM__", "WIN32"}
+ end
+
+ if os.is("Linux") then
+ defines {"__LINUX_ALSA__"}
+ links {"asound","pthread"}
+ end
+
+ if os.is("MacOSX") then
+ links{"CoreAudio.framework", "coreMIDI.framework", "Cocoa.framework"}
+ defines {"__MACOSX_CORE__"}
+ end
+
+ end
+
includedirs {
".","../../src", "../ThirdPartyLibs",
"../ThirdPartyLibs/openvr/headers",
@@ -288,4 +357,7 @@ if os.is("Windows") then
end
-end
\ No newline at end of file
+end
+
+
+include "udp"
diff --git a/examples/SharedMemory/udp/main.cpp b/examples/SharedMemory/udp/main.cpp
new file mode 100644
index 000000000..bc8c6c57d
--- /dev/null
+++ b/examples/SharedMemory/udp/main.cpp
@@ -0,0 +1,209 @@
+/* server.cpp */
+#include
+#include
+#include "../../CommonInterfaces/CommonGUIHelperInterface.h"
+#ifdef NO_SHARED_MEMORY
+ #include "PhysicsServerCommandProcessor.h"
+ typedef PhysicsServerCommandProcessor MyCommandProcessor;
+#else
+ #include "SharedMemoryCommandProcessor.h"
+ typedef SharedMemoryCommandProcessor MyCommandProcessor ;
+#endif //NO_SHARED_MEMORY
+#include "SharedMemoryCommands.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "PhysicsServerCommandProcessor.h"
+
+
+bool gVerboseNetworkMessagesServer = false;
+
+void MySerializeInt(unsigned int sz, unsigned char* output)
+{
+ unsigned int tmp = sz;
+ output[0] = tmp & 255;
+ tmp = tmp >> 8;
+ output[1] = tmp & 255;
+ tmp = tmp >> 8;
+ output[2] = tmp & 255;
+ tmp = tmp >> 8;
+ output[3] = tmp & 255;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+
+ DummyGUIHelper guiHelper;
+ PhysicsCommandProcessorInterface* sm = new MyCommandProcessor;
+ sm->setGuiHelper(&guiHelper);
+
+// PhysicsDirect* sm = new PhysicsDirect(sdk);
+
+ //PhysicsClientSharedMemory* sm = new PhysicsClientSharedMemory();
+
+ bool isPhysicsClientConnected = sm->connect();
+
+ if (isPhysicsClientConnected)
+ {
+
+ ENetAddress address;
+ ENetHost *server;
+ ENetEvent event;
+ int serviceResult;
+
+ puts("Starting server");
+
+ if (enet_initialize() != 0)
+ {
+ puts("Error initialising enet");
+ exit(EXIT_FAILURE);
+ }
+
+
+ /* Bind the server to the default localhost. */
+ /* A specific host address can be specified by */
+ /* enet_address_set_host (& address, "x.x.x.x"); */
+ address.host = ENET_HOST_ANY;
+ /* Bind the server to port 1234. */
+ address.port = 1234;
+
+ server = enet_host_create(&address,
+ 32, /* number of clients */
+ 2, /* number of channels */
+ 0, /* Any incoming bandwith */
+ 0); /* Any outgoing bandwith */
+
+ if (server == NULL)
+ {
+ puts("Could not create server host");
+ exit(EXIT_FAILURE);
+ }
+
+
+ while (true)
+ {
+ serviceResult = 1;
+
+ /* Keep doing host_service until no events are left */
+ while (serviceResult > 0)
+ {
+ /* Wait up to 1000 milliseconds for an event. */
+ serviceResult = enet_host_service(server, &event, 0);
+ if (serviceResult > 0)
+ {
+
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ {
+ printf("A new client connected from %x:%u.\n",
+ event.peer->address.host,
+ event.peer->address.port);
+
+ /* Store any relevant client information here. */
+ event.peer->data = (void*)"Client information";
+
+ break;
+ }
+ case ENET_EVENT_TYPE_RECEIVE:
+ {
+ if (gVerboseNetworkMessagesServer)
+ {
+ printf("A packet of length %u containing '%s' was "
+ "received from %s on channel %u.\n",
+ event.packet->dataLength,
+ event.packet->data,
+ event.peer->data,
+ event.channelID);
+ }
+ if (event.packet->dataLength == sizeof(SharedMemoryCommand))
+ {
+ SharedMemoryCommand* cmdPtr = (SharedMemoryCommand*)event.packet->data;
+ SharedMemoryStatus serverStatus;
+ b3AlignedObjectArray buffer;
+ buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
+
+ bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size());
+
+ int timeout = 1024 * 1024 * 1024;
+ while ((!hasStatus) && (timeout-- > 0))
+ {
+ hasStatus = sm->receiveStatus(serverStatus, &buffer[0], buffer.size());
+
+ }
+ if (gVerboseNetworkMessagesServer)
+ {
+ printf("buffer.size = %d\n", buffer.size());
+ printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes);
+ }
+ if (hasStatus)
+ {
+ //create packetData with [int packetSizeInBytes, status, streamBytes)
+ unsigned char* statBytes = (unsigned char*)&serverStatus;
+ b3AlignedObjectArray packetData;
+ packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes);
+ int sz = packetData.size();
+ int curPos = 0;
+
+ MySerializeInt(sz, &packetData[curPos]);
+ curPos += 4;
+ for (int i = 0; i < sizeof(SharedMemoryStatus); i++)
+ {
+ packetData[i + curPos] = statBytes[i];
+ }
+ curPos += sizeof(SharedMemoryStatus);
+
+ for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++)
+ {
+ packetData[i + curPos] = buffer[i];
+ }
+
+ ENetPacket *packet = enet_packet_create(&packetData[0], packetData.size() , ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send(event.peer, 0, packet);
+ //enet_host_broadcast(server, 0, packet);
+ }
+ }
+ else
+ {
+ printf("received packet with unknown contents\n");
+ }
+
+
+ /* Tell all clients about this message */
+ //enet_host_broadcast(server, 0, event.packet);
+
+ break;
+ }
+ case ENET_EVENT_TYPE_DISCONNECT:
+ {
+ printf("%s disconnected.\n", event.peer->data);
+
+ /* Reset the peer's client information. */
+
+ event.peer->data = NULL;
+
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+ }
+ else if (serviceResult > 0)
+ {
+ puts("Error with servicing the server");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ }
+
+ enet_host_destroy(server);
+ enet_deinitialize();
+ }
+ delete sm;
+
+ return 0;
+
+}
diff --git a/examples/SharedMemory/udp/premake4.lua b/examples/SharedMemory/udp/premake4.lua
new file mode 100644
index 000000000..531b098bf
--- /dev/null
+++ b/examples/SharedMemory/udp/premake4.lua
@@ -0,0 +1,126 @@
+
+project ("App_PhysicsServerSharedMemoryBridgeUDP")
+
+ language "C++"
+
+ kind "ConsoleApp"
+
+ includedirs {"../../ThirdPartyLibs/enet/include","../../../src",".."}
+
+ if os.is("Windows") then
+ defines { "WIN32" }
+
+
+ links {"Ws2_32","Winmm"}
+ end
+ if os.is("Linux") then
+ end
+ if os.is("MacOSX") then
+ end
+
+
+ links {
+ "enet",
+ "BulletFileLoader",
+ "Bullet3Common",
+ "LinearMath"
+ }
+
+ files {
+ "main.cpp",
+ "../PhysicsClient.cpp",
+ "../PhysicsClient.h",
+ "../PhysicsDirect.cpp",
+ "../PhysicsDirect.h",
+ "../PhysicsCommandProcessorInterface.h",
+ "../SharedMemoryCommandProcessor.cpp",
+ "../SharedMemoryCommandProcessor.h",
+ "../PhysicsClientC_API.cpp",
+ "../PhysicsClientC_API.h",
+ "../Win32SharedMemory.cpp",
+ "../Win32SharedMemory.h",
+ "../PosixSharedMemory.cpp",
+ "../PosixSharedMemory.h",
+ "../../Utils/b3ResourcePath.cpp",
+ "../../Utils/b3ResourcePath.h",
+ }
+
+
+project "App_PhysicsServerUDP"
+
+if _OPTIONS["ios"] then
+ kind "WindowedApp"
+else
+ kind "ConsoleApp"
+end
+
+defines { "NO_SHARED_MEMORY" }
+
+includedirs {"..","../../../src", "../../ThirdPartyLibs","../../ThirdPartyLibs/enet/include"}
+
+links {
+ "enet","Bullet3Common","BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision", "LinearMath", "BussIK"
+}
+
+if os.is("Windows") then
+ defines { "WIN32" }
+ links {"Ws2_32","Winmm"}
+end
+
+language "C++"
+
+myfiles =
+{
+ "../IKTrajectoryHelper.cpp",
+ "../IKTrajectoryHelper.h",
+ "../SharedMemoryCommands.h",
+ "../SharedMemoryPublic.h",
+ "../PhysicsServerCommandProcessor.cpp",
+ "../PhysicsServerCommandProcessor.h",
+ "../TinyRendererVisualShapeConverter.cpp",
+ "../TinyRendererVisualShapeConverter.h",
+ "../../TinyRenderer/geometry.cpp",
+ "../../TinyRenderer/model.cpp",
+ "../../TinyRenderer/tgaimage.cpp",
+ "../../TinyRenderer/our_gl.cpp",
+ "../../TinyRenderer/TinyRenderer.cpp",
+ "../../OpenGLWindow/SimpleCamera.cpp",
+ "../../OpenGLWindow/SimpleCamera.h",
+ "../../Importers/ImportURDFDemo/ConvertRigidBodies2MultiBody.h",
+ "../../Importers/ImportURDFDemo/MultiBodyCreationInterface.h",
+ "../../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
+ "../../Importers/ImportURDFDemo/MyMultiBodyCreator.h",
+ "../../Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
+ "../../Importers/ImportURDFDemo/BulletUrdfImporter.h",
+ "../../Importers/ImportURDFDemo/UrdfParser.cpp",
+ "../../Importers/ImportURDFDemo/urdfStringSplit.cpp",
+ "../../Importers/ImportURDFDemo/UrdfParser.cpp",
+ "../../Importers/ImportURDFDemo/UrdfParser.h",
+ "../../Importers/ImportURDFDemo/URDF2Bullet.cpp",
+ "../../Importers/ImportURDFDemo/URDF2Bullet.h",
+ "../../Utils/b3ResourcePath.cpp",
+ "../../Utils/b3Clock.cpp",
+ "../../../Extras/Serialize/BulletWorldImporter/*",
+ "../../../Extras/Serialize/BulletFileLoader/*",
+ "../../Importers/ImportURDFDemo/URDFImporterInterface.h",
+ "../../Importers/ImportURDFDemo/URDFJointTypes.h",
+ "../../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
+ "../../Importers/ImportObjDemo/LoadMeshFromObj.cpp",
+ "../../Importers/ImportSTLDemo/ImportSTLSetup.h",
+ "../../Importers/ImportSTLDemo/LoadMeshFromSTL.h",
+ "../../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
+ "../../Importers/ImportColladaDemo/ColladaGraphicsInstance.h",
+ "../../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
+ "../../ThirdPartyLibs/tinyxml/tinystr.cpp",
+ "../../ThirdPartyLibs/tinyxml/tinyxml.cpp",
+ "../../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
+ "../../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
+ "../../Importers/ImportMeshUtility/b3ImportMeshUtility.cpp",
+ "../../ThirdPartyLibs/stb_image/stb_image.cpp",
+}
+
+files {
+ myfiles,
+ "main.cpp",
+}
+
diff --git a/examples/SoftDemo/SoftDemo.cpp b/examples/SoftDemo/SoftDemo.cpp
index 7a046f9c4..49b59e444 100644
--- a/examples/SoftDemo/SoftDemo.cpp
+++ b/examples/SoftDemo/SoftDemo.cpp
@@ -2131,12 +2131,12 @@ void SoftDemo::initPhysics()
for (int j=0;jGetControllerState( unDevice, &state ) )
+ if( m_pHMD->GetControllerState( unDevice, &state ,sizeof(vr::VRControllerState_t)) )
{
//we need to have the 'move' events, so no early out here
//if (sPrevStates[unDevice].unPacketNum != state.unPacketNum)
@@ -776,12 +779,14 @@ void CMainApplication::RunMainLoop()
while ( !bQuit && !m_app->m_window->requestedExit())
{
+ {
B3_PROFILE("main");
bQuit = HandleInput();
RenderFrame();
}
+ }
}
@@ -844,7 +849,7 @@ void CMainApplication::RenderFrame()
// happen right before and after the vsync causing all kinds of jittering issues. This glFinish()
// appears to clear that up. Temporary fix while I try to get nvidia to investigate this problem.
// 1/29/2014 mikesart
- glFinish();
+ //glFinish();
}
// SwapWindow
@@ -1282,6 +1287,8 @@ void CMainApplication::AddCubeToScene( Matrix4 mat, std::vector &vertdata
//-----------------------------------------------------------------------------
// Purpose: Draw all of the controllers as X/Y/Z lines
//-----------------------------------------------------------------------------
+extern int gGraspingController;
+
void CMainApplication::DrawControllers()
{
// don't draw controllers if somebody else has input focus
@@ -1295,6 +1302,8 @@ void CMainApplication::DrawControllers()
for ( vr::TrackedDeviceIndex_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; ++unTrackedDevice )
{
+
+
if ( !m_pHMD->IsTrackedDeviceConnected( unTrackedDevice ) )
continue;
@@ -1479,8 +1488,9 @@ void CMainApplication::SetupDistortion()
u = x*w; v = 1-y*h;
vert.position = Vector2( Xoffset+u, -1+2*y*h );
- vr::DistortionCoordinates_t dc0 = m_pHMD->ComputeDistortion(vr::Eye_Left, u, v);
-
+ vr::DistortionCoordinates_t dc0;
+ bool result = m_pHMD->ComputeDistortion(vr::Eye_Left, u, v,&dc0);
+ btAssert(result);
vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]);
vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]);
vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]);
@@ -1498,8 +1508,9 @@ void CMainApplication::SetupDistortion()
u = x*w; v = 1-y*h;
vert.position = Vector2( Xoffset+u, -1+2*y*h );
- vr::DistortionCoordinates_t dc0 = m_pHMD->ComputeDistortion( vr::Eye_Right, u, v );
-
+ vr::DistortionCoordinates_t dc0;
+ bool result = m_pHMD->ComputeDistortion( vr::Eye_Right, u, v,&dc0 );
+ btAssert(result);
vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]);
vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]);
vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]);
@@ -2183,9 +2194,11 @@ void CGLRenderModel::Draw()
//-----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
+
+
#ifdef BT_USE_CUSTOM_PROFILER
- //b3SetCustomEnterProfileZoneFunc(...);
- //b3SetCustomLeaveProfileZoneFunc(...);
+ b3SetCustomEnterProfileZoneFunc(dcEnter);
+ b3SetCustomLeaveProfileZoneFunc(dcLeave);
#endif
@@ -2223,7 +2236,6 @@ int main(int argc, char *argv[])
pMainApplication->Shutdown();
#ifdef BT_USE_CUSTOM_PROFILER
-//...
#endif
return 0;
diff --git a/examples/StandaloneMain/main_opengl_single_example.cpp b/examples/StandaloneMain/main_opengl_single_example.cpp
index 8bf97619d..a040882c6 100644
--- a/examples/StandaloneMain/main_opengl_single_example.cpp
+++ b/examples/StandaloneMain/main_opengl_single_example.cpp
@@ -83,8 +83,11 @@ int main(int argc, char* argv[])
//DummyGUIHelper gui;
CommonExampleOptions options(&gui);
+
example = StandaloneExampleCreateFunc(options);
+ example->processCommandLineArgs(argc, argv);
+
example->initPhysics();
example->resetCamera();
diff --git a/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp
index 2ab5d3992..3dd8b2cce 100644
--- a/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp
+++ b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp
@@ -209,10 +209,13 @@ public:
renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
- renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
- renderObj->m_lightDirWorld = lightDirWorld;
}
}
+ renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
+ renderObj->m_lightDirWorld = lightDirWorld;
+ renderObj->m_lightAmbientCoeff = 0.6;
+ renderObj->m_lightDiffuseCoeff = 0.35;
+ renderObj->m_lightSpecularCoeff = 0.05;
TinyRenderer::renderObject(*renderObj);
}
}
diff --git a/examples/StandaloneMain/main_tinyrenderer_single_example.cpp b/examples/StandaloneMain/main_tinyrenderer_single_example.cpp
index 6ca0efa36..4ebda9d3b 100644
--- a/examples/StandaloneMain/main_tinyrenderer_single_example.cpp
+++ b/examples/StandaloneMain/main_tinyrenderer_single_example.cpp
@@ -230,10 +230,13 @@ struct TinyRendererGUIHelper : public GUIHelperInterface
renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
- renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
- renderObj->m_lightDirWorld = lightDirWorld;
}
}
+ renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
+ renderObj->m_lightDirWorld = lightDirWorld;
+ renderObj->m_lightAmbientCoeff = 0.6;
+ renderObj->m_lightDiffuseCoeff = 0.35;
+ renderObj->m_lightSpecularCoeff = 0.05;
TinyRenderer::renderObject(*renderObj);
}
}
@@ -379,6 +382,20 @@ struct TinyRendererGUIHelper : public GUIHelperInterface
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)
{
+ }
+ virtual int addUserDebugText3D( const char* txt, const double positionXYZ[3], const double textColorRGB[3], double size, double lifeTime)
+ {
+ return -1;
+ }
+ virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime )
+ {
+ return -1;
+ }
+ virtual void removeUserDebugItem( int debugItemUniqueId)
+ {
+ }
+ virtual void removeAllUserDebugItems( )
+ {
}
};
diff --git a/examples/ThirdPartyLibs/BussIK/Tree.cpp b/examples/ThirdPartyLibs/BussIK/Tree.cpp
index 6891f0601..0ce6486d8 100644
--- a/examples/ThirdPartyLibs/BussIK/Tree.cpp
+++ b/examples/ThirdPartyLibs/BussIK/Tree.cpp
@@ -98,10 +98,10 @@ Node* Tree::SearchJoint(Node* node, int index)
if (node->seqNumJoint == index) {
return node;
} else {
- if (ret = SearchJoint(node->left, index)) {
+ if ((ret = SearchJoint(node->left, index))) {
return ret;
}
- if (ret = SearchJoint(node->right, index)) {
+ if ((ret = SearchJoint(node->right, index))) {
return ret;
}
return NULL;
@@ -127,10 +127,10 @@ Node* Tree::SearchEffector(Node* node, int index)
if (node->seqNumEffector == index) {
return node;
} else {
- if (ret = SearchEffector(node->left, index)) {
+ if ((ret = SearchEffector(node->left, index))) {
return ret;
}
- if (ret = SearchEffector(node->right, index)) {
+ if ((ret = SearchEffector(node->right, index))) {
return ret;
}
return NULL;
@@ -214,4 +214,4 @@ void Tree::UnFreezeTree(Node* node)
void Tree::UnFreeze(void)
{
UnFreezeTree(root);
-}
\ No newline at end of file
+}
diff --git a/examples/ThirdPartyLibs/enet/premake4.lua b/examples/ThirdPartyLibs/enet/premake4.lua
index 522db3431..05390e766 100644
--- a/examples/ThirdPartyLibs/enet/premake4.lua
+++ b/examples/ThirdPartyLibs/enet/premake4.lua
@@ -14,8 +14,7 @@
files{"unix.c"}
end
- targetdir "../../../lib"
-
+
includedirs {
".","include"
}
diff --git a/examples/ThirdPartyLibs/midi/LICENSE.txt b/examples/ThirdPartyLibs/midi/LICENSE.txt
new file mode 100644
index 000000000..5b85f871c
--- /dev/null
+++ b/examples/ThirdPartyLibs/midi/LICENSE.txt
@@ -0,0 +1,29 @@
+ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
+
+ RtMidi: realtime MIDI i/o C++ classes
+ Copyright (c) 2003-2012 Gary P. Scavone
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ asked to send the modifications to the original developer so that
+ they can be incorporated into the canonical version. This is,
+ however, not a binding provision of this license.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
\ No newline at end of file
diff --git a/examples/ThirdPartyLibs/midi/RtError.h b/examples/ThirdPartyLibs/midi/RtError.h
new file mode 100644
index 000000000..5cf7d510a
--- /dev/null
+++ b/examples/ThirdPartyLibs/midi/RtError.h
@@ -0,0 +1,60 @@
+/************************************************************************/
+/*! \class RtError
+\brief Exception handling class for RtAudio & RtMidi.
+
+The RtError class is quite simple but it does allow errors to be
+"caught" by RtError::Type. See the RtAudio and RtMidi
+documentation to know which methods can throw an RtError.
+
+*/
+/************************************************************************/
+
+#ifndef RTERROR_H
+#define RTERROR_H
+
+#include
+#include
+#include
+
+class RtError : public std::exception
+{
+public:
+ //! Defined RtError types.
+ enum Type {
+ WARNING, /*!< A non-critical error. */
+ DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */
+ UNSPECIFIED, /*!< The default, unspecified error type. */
+ NO_DEVICES_FOUND, /*!< No devices found on system. */
+ INVALID_DEVICE, /*!< An invalid device ID was specified. */
+ MEMORY_ERROR, /*!< An error occured during memory allocation. */
+ INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */
+ INVALID_USE, /*!< The function was called incorrectly. */
+ DRIVER_ERROR, /*!< A system driver error occured. */
+ SYSTEM_ERROR, /*!< A system error occured. */
+ THREAD_ERROR /*!< A thread error occured. */
+ };
+
+ //! The constructor.
+ RtError(const std::string& message, Type type = RtError::UNSPECIFIED) throw() : message_(message), type_(type) {}
+
+ //! The destructor.
+ virtual ~RtError(void) throw() {}
+
+ //! Prints thrown error message to stderr.
+ virtual void printMessage(void) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
+
+ //! Returns the thrown error message type.
+ virtual const Type& getType(void) const throw() { return type_; }
+
+ //! Returns the thrown error message string.
+ virtual const std::string& getMessage(void) const throw() { return message_; }
+
+ //! Returns the thrown error message as a c-style string.
+ virtual const char* what(void) const throw() { return message_.c_str(); }
+
+protected:
+ std::string message_;
+ Type type_;
+};
+
+#endif
\ No newline at end of file
diff --git a/examples/ThirdPartyLibs/midi/RtMidi.cpp b/examples/ThirdPartyLibs/midi/RtMidi.cpp
new file mode 100644
index 000000000..9cbd260f0
--- /dev/null
+++ b/examples/ThirdPartyLibs/midi/RtMidi.cpp
@@ -0,0 +1,3803 @@
+/**********************************************************************/
+/*! \class RtMidi
+ \brief An abstract base class for realtime MIDI input/output.
+
+ This class implements some common functionality for the realtime
+ MIDI input/output subclasses RtMidiIn and RtMidiOut.
+
+ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
+
+ RtMidi: realtime MIDI i/o C++ classes
+ Copyright (c) 2003-2012 Gary P. Scavone
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ asked to send the modifications to the original developer so that
+ they can be incorporated into the canonical version. This is,
+ however, not a binding provision of this license.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+/**********************************************************************/
+
+// RtMidi: Version 2.0.1
+
+#include "RtMidi.h"
+#include
+#include //exit
+
+//*********************************************************************//
+// RtMidi Definitions
+//*********************************************************************//
+
+void RtMidi :: getCompiledApi( std::vector &apis )
+{
+ apis.clear();
+
+ // The order here will control the order of RtMidi's API search in
+ // the constructor.
+#if defined(__MACOSX_CORE__)
+ apis.push_back( MACOSX_CORE );
+#endif
+#if defined(__LINUX_ALSA__)
+ apis.push_back( LINUX_ALSA );
+#endif
+#if defined(__UNIX_JACK__)
+ apis.push_back( UNIX_JACK );
+#endif
+#if defined(__WINDOWS_MM__)
+ apis.push_back( WINDOWS_MM );
+#endif
+#if defined(__WINDOWS_KS__)
+ apis.push_back( WINDOWS_KS );
+#endif
+#if defined(__RTMIDI_DUMMY__)
+ apis.push_back( RTMIDI_DUMMY );
+#endif
+
+}
+
+void RtMidi :: error( RtError::Type type, std::string errorString )
+{
+ if (type == RtError::WARNING) {
+ std::cerr << '\n' << errorString << "\n\n";
+ }
+ else if (type == RtError::DEBUG_WARNING) {
+#if defined(__RTMIDI_DEBUG__)
+ std::cerr << '\n' << errorString << "\n\n";
+#endif
+ }
+ else {
+ std::cerr << '\n' << errorString << "\n\n";
+// exit(0);
+ }
+}
+
+//*********************************************************************//
+// RtMidiIn Definitions
+//*********************************************************************//
+
+void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit )
+{
+ if ( rtapi_ )
+ delete rtapi_;
+ rtapi_ = 0;
+
+#if defined(__UNIX_JACK__)
+ if ( api == UNIX_JACK )
+ rtapi_ = new MidiInJack( clientName, queueSizeLimit );
+#endif
+#if defined(__LINUX_ALSA__)
+ if ( api == LINUX_ALSA )
+ rtapi_ = new MidiInAlsa( clientName, queueSizeLimit );
+#endif
+#if defined(__WINDOWS_MM__)
+ if ( api == WINDOWS_MM )
+ rtapi_ = new MidiInWinMM( clientName, queueSizeLimit );
+#endif
+#if defined(__WINDOWS_KS__)
+ if ( api == WINDOWS_KS )
+ rtapi_ = new MidiInWinKS( clientName, queueSizeLimit );
+#endif
+#if defined(__MACOSX_CORE__)
+ if ( api == MACOSX_CORE )
+ rtapi_ = new MidiInCore( clientName, queueSizeLimit );
+#endif
+#if defined(__RTMIDI_DUMMY__)
+ if ( api == RTMIDI_DUMMY )
+ rtapi_ = new MidiInDummy( clientName, queueSizeLimit );
+#endif
+}
+
+RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit )
+{
+ rtapi_ = 0;
+
+ if ( api != UNSPECIFIED ) {
+ // Attempt to open the specified API.
+ openMidiApi( api, clientName, queueSizeLimit );
+ if ( rtapi_ ) return;
+
+ // No compiled support for specified API value. Issue a debug
+ // warning and continue as if no API was specified.
+ RtMidi::error( RtError::WARNING, "RtMidiIn: no compiled support for specified API argument!" );
+ }
+
+ // Iterate through the compiled APIs and return as soon as we find
+ // one with at least one port or we reach the end of the list.
+ std::vector< RtMidi::Api > apis;
+ getCompiledApi( apis );
+ for ( unsigned int i=0; igetPortCount() ) break;
+ }
+
+ if ( rtapi_ ) return;
+
+ // It should not be possible to get here because the preprocessor
+ // definition __RTMIDI_DUMMY__ is automatically defined if no
+ // API-specific definitions are passed to the compiler. But just in
+ // case something weird happens, we'll print out an error message.
+ RtMidi::error( RtError::WARNING, "RtMidiIn: no compiled API support found ... critical error!!" );
+}
+
+RtMidiIn :: ~RtMidiIn()
+{
+ delete rtapi_;
+}
+
+
+//*********************************************************************//
+// RtMidiOut Definitions
+//*********************************************************************//
+
+void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName )
+{
+ if ( rtapi_ )
+ delete rtapi_;
+ rtapi_ = 0;
+
+#if defined(__UNIX_JACK__)
+ if ( api == UNIX_JACK )
+ rtapi_ = new MidiOutJack( clientName );
+#endif
+#if defined(__LINUX_ALSA__)
+ if ( api == LINUX_ALSA )
+ rtapi_ = new MidiOutAlsa( clientName );
+#endif
+#if defined(__WINDOWS_MM__)
+ if ( api == WINDOWS_MM )
+ rtapi_ = new MidiOutWinMM( clientName );
+#endif
+#if defined(__WINDOWS_KS__)
+ if ( api == WINDOWS_KS )
+ rtapi_ = new MidiOutWinKS( clientName );
+#endif
+#if defined(__MACOSX_CORE__)
+ if ( api == MACOSX_CORE )
+ rtapi_ = new MidiOutCore( clientName );
+#endif
+#if defined(__RTMIDI_DUMMY__)
+ if ( api == RTMIDI_DUMMY )
+ rtapi_ = new MidiOutDummy( clientName );
+#endif
+}
+
+RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName )
+{
+ rtapi_ = 0;
+
+ if ( api != UNSPECIFIED ) {
+ // Attempt to open the specified API.
+ openMidiApi( api, clientName );
+ if ( rtapi_ ) return;
+
+ // No compiled support for specified API value. Issue a debug
+ // warning and continue as if no API was specified.
+ RtMidi::error( RtError::WARNING, "RtMidiOut: no compiled support for specified API argument!" );
+ }
+
+ // Iterate through the compiled APIs and return as soon as we find
+ // one with at least one port or we reach the end of the list.
+ std::vector< RtMidi::Api > apis;
+ getCompiledApi( apis );
+ for ( unsigned int i=0; igetPortCount() ) break;
+ }
+
+ if ( rtapi_ ) return;
+
+ // It should not be possible to get here because the preprocessor
+ // definition __RTMIDI_DUMMY__ is automatically defined if no
+ // API-specific definitions are passed to the compiler. But just in
+ // case something weird happens, we'll print out an error message.
+ RtMidi::error( RtError::WARNING, "RtMidiOut: no compiled API support found ... critical error!!" );
+}
+
+RtMidiOut :: ~RtMidiOut()
+{
+ delete rtapi_;
+}
+
+//*********************************************************************//
+// Common MidiInApi Definitions
+//*********************************************************************//
+
+MidiInApi :: MidiInApi( unsigned int queueSizeLimit )
+ : apiData_( 0 ), connected_( false )
+{
+ // Allocate the MIDI queue.
+ inputData_.queue.ringSize = queueSizeLimit;
+ if ( inputData_.queue.ringSize > 0 )
+ inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ];
+}
+
+MidiInApi :: ~MidiInApi( void )
+{
+ // Delete the MIDI queue.
+ if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring;
+}
+
+void MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData )
+{
+ if ( inputData_.usingCallback ) {
+ errorString_ = "MidiInApi::setCallback: a callback function is already set!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ if ( !callback ) {
+ errorString_ = "RtMidiIn::setCallback: callback function value is invalid!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ inputData_.userCallback = (void *) callback;
+ inputData_.userData = userData;
+ inputData_.usingCallback = true;
+}
+
+void MidiInApi :: cancelCallback()
+{
+ if ( !inputData_.usingCallback ) {
+ errorString_ = "RtMidiIn::cancelCallback: no callback function was set!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ inputData_.userCallback = 0;
+ inputData_.userData = 0;
+ inputData_.usingCallback = false;
+}
+
+void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense )
+{
+ inputData_.ignoreFlags = 0;
+ if ( midiSysex ) inputData_.ignoreFlags = 0x01;
+ if ( midiTime ) inputData_.ignoreFlags |= 0x02;
+ if ( midiSense ) inputData_.ignoreFlags |= 0x04;
+}
+
+double MidiInApi :: getMessage( std::vector *message )
+{
+ message->clear();
+
+ if ( inputData_.usingCallback ) {
+ errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return 0.0;
+ }
+
+ if ( inputData_.queue.size == 0 ) return 0.0;
+
+ // Copy queued message to the vector pointer argument and then "pop" it.
+ std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes);
+ message->assign( bytes->begin(), bytes->end() );
+ double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp;
+ inputData_.queue.size--;
+ inputData_.queue.front++;
+ if ( inputData_.queue.front == inputData_.queue.ringSize )
+ inputData_.queue.front = 0;
+
+ return deltaTime;
+}
+
+//*********************************************************************//
+// Common MidiOutApi Definitions
+//*********************************************************************//
+
+MidiOutApi :: MidiOutApi( void )
+ : apiData_( 0 ), connected_( false )
+{
+}
+
+MidiOutApi :: ~MidiOutApi( void )
+{
+}
+
+// *************************************************** //
+//
+// OS/API-specific methods.
+//
+// *************************************************** //
+
+#if defined(__MACOSX_CORE__)
+
+// The CoreMIDI API is based on the use of a callback function for
+// MIDI input. We convert the system specific time stamps to delta
+// time values.
+
+// OS-X CoreMIDI header files.
+#include
+#include
+#include
+
+// A structure to hold variables related to the CoreMIDI API
+// implementation.
+struct CoreMidiData {
+ MIDIClientRef client;
+ MIDIPortRef port;
+ MIDIEndpointRef endpoint;
+ MIDIEndpointRef destinationId;
+ unsigned long long lastTime;
+ MIDISysexSendRequest sysexreq;
+};
+
+//*********************************************************************//
+// API: OS-X
+// Class Definitions: MidiInCore
+//*********************************************************************//
+
+void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef )
+{
+ MidiInApi::RtMidiInData *data = static_cast (procRef);
+ CoreMidiData *apiData = static_cast (data->apiData);
+
+ unsigned char status;
+ unsigned short nBytes, iByte, size;
+ unsigned long long time;
+
+ bool& continueSysex = data->continueSysex;
+ MidiInApi::MidiMessage& message = data->message;
+
+ const MIDIPacket *packet = &list->packet[0];
+ for ( unsigned int i=0; inumPackets; ++i ) {
+
+ // My interpretation of the CoreMIDI documentation: all message
+ // types, except sysex, are complete within a packet and there may
+ // be several of them in a single packet. Sysex messages can be
+ // broken across multiple packets and PacketLists but are bundled
+ // alone within each packet (these packets do not contain other
+ // message types). If sysex messages are split across multiple
+ // MIDIPacketLists, they must be handled by multiple calls to this
+ // function.
+
+ nBytes = packet->length;
+ if ( nBytes == 0 ) continue;
+
+ // Calculate time stamp.
+
+ if ( data->firstMessage ) {
+ message.timeStamp = 0.0;
+ data->firstMessage = false;
+ }
+ else {
+ time = packet->timeStamp;
+ if ( time == 0 ) { // this happens when receiving asynchronous sysex messages
+ time = AudioGetCurrentHostTime();
+ }
+ time -= apiData->lastTime;
+ time = AudioConvertHostTimeToNanos( time );
+ if ( !continueSysex )
+ message.timeStamp = time * 0.000000001;
+ }
+ apiData->lastTime = packet->timeStamp;
+ if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages
+ apiData->lastTime = AudioGetCurrentHostTime();
+ }
+ //std::cout << "TimeStamp = " << packet->timeStamp << std::endl;
+
+ iByte = 0;
+ if ( continueSysex ) {
+ // We have a continuing, segmented sysex message.
+ if ( !( data->ignoreFlags & 0x01 ) ) {
+ // If we're not ignoring sysex messages, copy the entire packet.
+ for ( unsigned int j=0; jdata[j] );
+ }
+ continueSysex = packet->data[nBytes-1] != 0xF7;
+
+ if ( !continueSysex ) {
+ // If not a continuing sysex message, invoke the user callback function or queue the message.
+ if ( data->usingCallback ) {
+ RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+ callback( message.timeStamp, &message.bytes, data->userData );
+ }
+ else {
+ // As long as we haven't reached our queue size limit, push the message.
+ if ( data->queue.size < data->queue.ringSize ) {
+ data->queue.ring[data->queue.back++] = message;
+ if ( data->queue.back == data->queue.ringSize )
+ data->queue.back = 0;
+ data->queue.size++;
+ }
+ else
+ std::cerr << "\nMidiInCore: message queue limit reached!!\n\n";
+ }
+ message.bytes.clear();
+ }
+ }
+ else {
+ while ( iByte < nBytes ) {
+ size = 0;
+ // We are expecting that the next byte in the packet is a status byte.
+ status = packet->data[iByte];
+ if ( !(status & 0x80) ) break;
+ // Determine the number of bytes in the MIDI message.
+ if ( status < 0xC0 ) size = 3;
+ else if ( status < 0xE0 ) size = 2;
+ else if ( status < 0xF0 ) size = 3;
+ else if ( status == 0xF0 ) {
+ // A MIDI sysex
+ if ( data->ignoreFlags & 0x01 ) {
+ size = 0;
+ iByte = nBytes;
+ }
+ else size = nBytes - iByte;
+ continueSysex = packet->data[nBytes-1] != 0xF7;
+ }
+ else if ( status == 0xF1 ) {
+ // A MIDI time code message
+ if ( data->ignoreFlags & 0x02 ) {
+ size = 0;
+ iByte += 2;
+ }
+ else size = 2;
+ }
+ else if ( status == 0xF2 ) size = 3;
+ else if ( status == 0xF3 ) size = 2;
+ else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) {
+ // A MIDI timing tick message and we're ignoring it.
+ size = 0;
+ iByte += 1;
+ }
+ else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) {
+ // A MIDI active sensing message and we're ignoring it.
+ size = 0;
+ iByte += 1;
+ }
+ else size = 1;
+
+ // Copy the MIDI data to our vector.
+ if ( size ) {
+ message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] );
+ if ( !continueSysex ) {
+ // If not a continuing sysex message, invoke the user callback function or queue the message.
+ if ( data->usingCallback ) {
+ RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+ callback( message.timeStamp, &message.bytes, data->userData );
+ }
+ else {
+ // As long as we haven't reached our queue size limit, push the message.
+ if ( data->queue.size < data->queue.ringSize ) {
+ data->queue.ring[data->queue.back++] = message;
+ if ( data->queue.back == data->queue.ringSize )
+ data->queue.back = 0;
+ data->queue.size++;
+ }
+ else
+ std::cerr << "\nMidiInCore: message queue limit reached!!\n\n";
+ }
+ message.bytes.clear();
+ }
+ iByte += size;
+ }
+ }
+ }
+ packet = MIDIPacketNext(packet);
+ }
+}
+
+MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )
+{
+ initialize( clientName );
+}
+
+MidiInCore :: ~MidiInCore( void )
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ CoreMidiData *data = static_cast (apiData_);
+ MIDIClientDispose( data->client );
+ if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );
+ delete data;
+}
+
+void MidiInCore :: initialize( const std::string& clientName )
+{
+ // Set up our client.
+ MIDIClientRef client;
+ OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client );
+ if ( result != noErr ) {
+ errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ CoreMidiData *data = (CoreMidiData *) new CoreMidiData;
+ data->client = client;
+ data->endpoint = 0;
+ apiData_ = (void *) data;
+ inputData_.apiData = (void *) data;
+}
+
+void MidiInCore :: openPort( unsigned int portNumber, const std::string portName )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiInCore::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nSrc = MIDIGetNumberOfSources();
+ if (nSrc < 1) {
+ errorString_ = "MidiInCore::openPort: no MIDI input sources found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ std::ostringstream ost;
+ if ( portNumber >= nSrc ) {
+ ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ MIDIPortRef port;
+ CoreMidiData *data = static_cast (apiData_);
+ OSStatus result = MIDIInputPortCreate( data->client,
+ CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
+ midiInputCallback, (void *)&inputData_, &port );
+ if ( result != noErr ) {
+ MIDIClientDispose( data->client );
+ errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Get the desired input source identifier.
+ MIDIEndpointRef endpoint = MIDIGetSource( portNumber );
+ if ( endpoint == 0 ) {
+ MIDIPortDispose( port );
+ MIDIClientDispose( data->client );
+ errorString_ = "MidiInCore::openPort: error getting MIDI input source reference.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Make the connection.
+ result = MIDIPortConnectSource( port, endpoint, NULL );
+ if ( result != noErr ) {
+ MIDIPortDispose( port );
+ MIDIClientDispose( data->client );
+ errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific port information.
+ data->port = port;
+
+ connected_ = true;
+}
+
+void MidiInCore :: openVirtualPort( const std::string portName )
+{
+ CoreMidiData *data = static_cast (apiData_);
+
+ // Create a virtual MIDI input destination.
+ MIDIEndpointRef endpoint;
+ OSStatus result = MIDIDestinationCreate( data->client,
+ CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
+ midiInputCallback, (void *)&inputData_, &endpoint );
+ if ( result != noErr ) {
+ errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ data->endpoint = endpoint;
+}
+
+void MidiInCore :: closePort( void )
+{
+ if ( connected_ ) {
+ CoreMidiData *data = static_cast (apiData_);
+ MIDIPortDispose( data->port );
+ connected_ = false;
+ }
+}
+
+unsigned int MidiInCore :: getPortCount()
+{
+ return MIDIGetNumberOfSources();
+}
+
+// This function was submitted by Douglas Casey Tucker and apparently
+// derived largely from PortMidi.
+CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal )
+{
+ CFMutableStringRef result = CFStringCreateMutable( NULL, 0 );
+ CFStringRef str;
+
+ // Begin with the endpoint's name.
+ str = NULL;
+ MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str );
+ if ( str != NULL ) {
+ CFStringAppend( result, str );
+ CFRelease( str );
+ }
+
+ MIDIEntityRef entity = NULL;
+ MIDIEndpointGetEntity( endpoint, &entity );
+ if ( entity == 0 )
+ // probably virtual
+ return result;
+
+ if ( CFStringGetLength( result ) == 0 ) {
+ // endpoint name has zero length -- try the entity
+ str = NULL;
+ MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str );
+ if ( str != NULL ) {
+ CFStringAppend( result, str );
+ CFRelease( str );
+ }
+ }
+ // now consider the device's name
+ MIDIDeviceRef device = 0;
+ MIDIEntityGetDevice( entity, &device );
+ if ( device == 0 )
+ return result;
+
+ str = NULL;
+ MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str );
+ if ( CFStringGetLength( result ) == 0 ) {
+ CFRelease( result );
+ return str;
+ }
+ if ( str != NULL ) {
+ // if an external device has only one entity, throw away
+ // the endpoint name and just use the device name
+ if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) {
+ CFRelease( result );
+ return str;
+ } else {
+ if ( CFStringGetLength( str ) == 0 ) {
+ CFRelease( str );
+ return result;
+ }
+ // does the entity name already start with the device name?
+ // (some drivers do this though they shouldn't)
+ // if so, do not prepend
+ if ( CFStringCompareWithOptions( result, /* endpoint name */
+ str /* device name */,
+ CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) {
+ // prepend the device name to the entity name
+ if ( CFStringGetLength( result ) > 0 )
+ CFStringInsert( result, 0, CFSTR(" ") );
+ CFStringInsert( result, 0, str );
+ }
+ CFRelease( str );
+ }
+ }
+ return result;
+}
+
+// This function was submitted by Douglas Casey Tucker and apparently
+// derived largely from PortMidi.
+static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint )
+{
+ CFMutableStringRef result = CFStringCreateMutable( NULL, 0 );
+ CFStringRef str;
+ OSStatus err;
+ int i;
+
+ // Does the endpoint have connections?
+ CFDataRef connections = NULL;
+ int nConnected = 0;
+ bool anyStrings = false;
+ err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections );
+ if ( connections != NULL ) {
+ // It has connections, follow them
+ // Concatenate the names of all connected devices
+ nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID);
+ if ( nConnected ) {
+ const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections));
+ for ( i=0; i= MIDIGetNumberOfSources() ) {
+ ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ return stringName;
+ }
+
+ portRef = MIDIGetSource( portNumber );
+ nameRef = ConnectedEndpointName(portRef);
+ CFStringGetCString( nameRef, name, sizeof(name), 0);
+ CFRelease( nameRef );
+
+ return stringName = name;
+}
+
+//*********************************************************************//
+// API: OS-X
+// Class Definitions: MidiOutCore
+//*********************************************************************//
+
+MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi()
+{
+ initialize( clientName );
+}
+
+MidiOutCore :: ~MidiOutCore( void )
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ CoreMidiData *data = static_cast (apiData_);
+ MIDIClientDispose( data->client );
+ if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );
+ delete data;
+}
+
+void MidiOutCore :: initialize( const std::string& clientName )
+{
+ // Set up our client.
+ MIDIClientRef client;
+ OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client );
+ if ( result != noErr ) {
+ errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ CoreMidiData *data = (CoreMidiData *) new CoreMidiData;
+ data->client = client;
+ data->endpoint = 0;
+ apiData_ = (void *) data;
+}
+
+unsigned int MidiOutCore :: getPortCount()
+{
+ return MIDIGetNumberOfDestinations();
+}
+
+std::string MidiOutCore :: getPortName( unsigned int portNumber )
+{
+ CFStringRef nameRef;
+ MIDIEndpointRef portRef;
+ std::ostringstream ost;
+ char name[128];
+
+ std::string stringName;
+ if ( portNumber >= MIDIGetNumberOfDestinations() ) {
+ ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return stringName;
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ portRef = MIDIGetDestination( portNumber );
+ nameRef = ConnectedEndpointName(portRef);
+ CFStringGetCString( nameRef, name, sizeof(name), 0);
+ CFRelease( nameRef );
+
+ return stringName = name;
+}
+
+void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiOutCore::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nDest = MIDIGetNumberOfDestinations();
+ if (nDest < 1) {
+ errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ std::ostringstream ost;
+ if ( portNumber >= nDest ) {
+ ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ MIDIPortRef port;
+ CoreMidiData *data = static_cast (apiData_);
+ OSStatus result = MIDIOutputPortCreate( data->client,
+ CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
+ &port );
+ if ( result != noErr ) {
+ MIDIClientDispose( data->client );
+ errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Get the desired output port identifier.
+ MIDIEndpointRef destination = MIDIGetDestination( portNumber );
+ if ( destination == 0 ) {
+ MIDIPortDispose( port );
+ MIDIClientDispose( data->client );
+ errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ data->port = port;
+ data->destinationId = destination;
+ connected_ = true;
+}
+
+void MidiOutCore :: closePort( void )
+{
+ if ( connected_ ) {
+ CoreMidiData *data = static_cast (apiData_);
+ MIDIPortDispose( data->port );
+ connected_ = false;
+ }
+}
+
+void MidiOutCore :: openVirtualPort( std::string portName )
+{
+ CoreMidiData *data = static_cast (apiData_);
+
+ if ( data->endpoint ) {
+ errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ // Create a virtual MIDI output source.
+ MIDIEndpointRef endpoint;
+ OSStatus result = MIDISourceCreate( data->client,
+ CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
+ &endpoint );
+ if ( result != noErr ) {
+ errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ data->endpoint = endpoint;
+}
+
+char *sysexBuffer = 0;
+
+void sysexCompletionProc( MIDISysexSendRequest * sreq )
+{
+ //std::cout << "Completed SysEx send\n";
+ delete sysexBuffer;
+ sysexBuffer = 0;
+}
+
+void MidiOutCore :: sendMessage( std::vector *message )
+{
+ // We use the MIDISendSysex() function to asynchronously send sysex
+ // messages. Otherwise, we use a single CoreMidi MIDIPacket.
+ unsigned int nBytes = message->size();
+ if ( nBytes == 0 ) {
+ errorString_ = "MidiOutCore::sendMessage: no data in message argument!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ // unsigned int packetBytes, bytesLeft = nBytes;
+ // unsigned int messageIndex = 0;
+ MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
+ CoreMidiData *data = static_cast (apiData_);
+ OSStatus result;
+
+ if ( message->at(0) == 0xF0 ) {
+
+ while ( sysexBuffer != 0 ) usleep( 1000 ); // sleep 1 ms
+
+ sysexBuffer = new char[nBytes];
+ if ( sysexBuffer == NULL ) {
+ errorString_ = "MidiOutCore::sendMessage: error allocating sysex message memory!";
+ RtMidi::error( RtError::MEMORY_ERROR, errorString_ );
+ }
+
+ // Copy data to buffer.
+ for ( unsigned int i=0; iat(i);
+
+ data->sysexreq.destination = data->destinationId;
+ data->sysexreq.data = (Byte *)sysexBuffer;
+ data->sysexreq.bytesToSend = nBytes;
+ data->sysexreq.complete = 0;
+ data->sysexreq.completionProc = sysexCompletionProc;
+ data->sysexreq.completionRefCon = &(data->sysexreq);
+
+ result = MIDISendSysex( &(data->sysexreq) );
+ if ( result != noErr ) {
+ errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+ return;
+ }
+ else if ( nBytes > 3 ) {
+ errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ MIDIPacketList packetList;
+ MIDIPacket *packet = MIDIPacketListInit( &packetList );
+ packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );
+ if ( !packet ) {
+ errorString_ = "MidiOutCore::sendMessage: could not allocate packet list";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Send to any destinations that may have connected to us.
+ if ( data->endpoint ) {
+ result = MIDIReceived( data->endpoint, &packetList );
+ if ( result != noErr ) {
+ errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+ }
+
+ // And send to an explicit destination port if we're connected.
+ if ( connected_ ) {
+ result = MIDISend( data->port, data->destinationId, &packetList );
+ if ( result != noErr ) {
+ errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+ }
+
+}
+
+#endif // __MACOSX_CORE__
+
+
+//*********************************************************************//
+// API: LINUX ALSA SEQUENCER
+//*********************************************************************//
+
+// API information found at:
+// - http://www.alsa-project.org/documentation.php#Library
+
+#if defined(__LINUX_ALSA__)
+
+// The ALSA Sequencer API is based on the use of a callback function for
+// MIDI input.
+//
+// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer
+// time stamps and other assorted fixes!!!
+
+// If you don't need timestamping for incoming MIDI events, define the
+// preprocessor definition AVOID_TIMESTAMPING to save resources
+// associated with the ALSA sequencer queues.
+
+#include
+#include
+
+// ALSA header file.
+#include
+
+// Global sequencer instance created when first In/Out object is
+// created, then destroyed when last In/Out is deleted.
+static snd_seq_t *s_seq = NULL;
+
+// Variable to keep track of how many ports are open.
+static unsigned int s_numPorts = 0;
+
+// The client name to use when creating the sequencer, which is
+// currently set on the first call to createSequencer.
+static std::string s_clientName = "RtMidi Client";
+
+// A structure to hold variables related to the ALSA API
+// implementation.
+struct AlsaMidiData {
+ snd_seq_t *seq;
+ unsigned int portNum;
+ int vport;
+ snd_seq_port_subscribe_t *subscription;
+ snd_midi_event_t *coder;
+ unsigned int bufferSize;
+ unsigned char *buffer;
+ pthread_t thread;
+ pthread_t dummy_thread_id;
+ unsigned long long lastTime;
+ int queue_id; // an input queue is needed to get timestamped events
+ int trigger_fds[2];
+};
+
+#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
+
+snd_seq_t* createSequencer( const std::string& clientName )
+{
+ // Set up the ALSA sequencer client.
+ if ( s_seq == NULL ) {
+ int result = snd_seq_open(&s_seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK);
+ if ( result < 0 ) {
+ s_seq = NULL;
+ }
+ else {
+ // Set client name, use current name if given string is empty.
+ if ( clientName != "" ) {
+ s_clientName = clientName;
+ }
+ snd_seq_set_client_name( s_seq, s_clientName.c_str() );
+ }
+ }
+
+ // Increment port count.
+ s_numPorts++;
+
+ return s_seq;
+}
+
+void freeSequencer ( void )
+{
+ s_numPorts--;
+ if ( s_numPorts == 0 && s_seq != NULL ) {
+ snd_seq_close( s_seq );
+ s_seq = NULL;
+ }
+}
+
+//*********************************************************************//
+// API: LINUX ALSA
+// Class Definitions: MidiInAlsa
+//*********************************************************************//
+
+extern "C" void *alsaMidiHandler( void *ptr )
+{
+ MidiInApi::RtMidiInData *data = static_cast (ptr);
+ AlsaMidiData *apiData = static_cast (data->apiData);
+
+ long nBytes;
+ unsigned long long time, lastTime;
+ bool continueSysex = false;
+ bool doDecode = false;
+ MidiInApi::MidiMessage message;
+ int poll_fd_count;
+ struct pollfd *poll_fds;
+
+ snd_seq_event_t *ev;
+ int result;
+ apiData->bufferSize = 32;
+ result = snd_midi_event_new( 0, &apiData->coder );
+ if ( result < 0 ) {
+ data->doInput = false;
+ std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n";
+ return 0;
+ }
+ unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize );
+ if ( buffer == NULL ) {
+ data->doInput = false;
+ snd_midi_event_free( apiData->coder );
+ apiData->coder = 0;
+ std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n";
+ return 0;
+ }
+ snd_midi_event_init( apiData->coder );
+ snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages
+
+ poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1;
+ poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd ));
+ snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN );
+ poll_fds[0].fd = apiData->trigger_fds[0];
+ poll_fds[0].events = POLLIN;
+
+ while ( data->doInput ) {
+
+ if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) {
+ // No data pending
+ if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) {
+ if ( poll_fds[0].revents & POLLIN ) {
+ bool dummy;
+ int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) );
+ (void) res;
+ }
+ }
+ continue;
+ }
+
+ // If here, there should be data.
+ result = snd_seq_event_input( apiData->seq, &ev );
+ if ( result == -ENOSPC ) {
+ std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n";
+ continue;
+ }
+ else if ( result <= 0 ) {
+ std::cerr << "MidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n";
+ continue;
+ }
+
+ // This is a bit weird, but we now have to decode an ALSA MIDI
+ // event (back) into MIDI bytes. We'll ignore non-MIDI types.
+ if ( !continueSysex ) message.bytes.clear();
+
+ doDecode = false;
+ switch ( ev->type ) {
+
+ case SND_SEQ_EVENT_PORT_SUBSCRIBED:
+#if defined(__RTMIDI_DEBUG__)
+ std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n";
+#endif
+ break;
+
+ case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
+#if defined(__RTMIDI_DEBUG__)
+ std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n";
+ std::cout << "sender = " << (int) ev->data.connect.sender.client << ":"
+ << (int) ev->data.connect.sender.port
+ << ", dest = " << (int) ev->data.connect.dest.client << ":"
+ << (int) ev->data.connect.dest.port
+ << std::endl;
+#endif
+ break;
+
+ case SND_SEQ_EVENT_QFRAME: // MIDI time code
+ if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true;
+ break;
+
+ case SND_SEQ_EVENT_TICK: // MIDI timing tick
+ if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true;
+ break;
+
+ case SND_SEQ_EVENT_SENSING: // Active sensing
+ if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true;
+ break;
+
+ case SND_SEQ_EVENT_SYSEX:
+ if ( (data->ignoreFlags & 0x01) ) break;
+ if ( ev->data.ext.len > apiData->bufferSize ) {
+ apiData->bufferSize = ev->data.ext.len;
+ free( buffer );
+ buffer = (unsigned char *) malloc( apiData->bufferSize );
+ if ( buffer == NULL ) {
+ data->doInput = false;
+ std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n";
+ break;
+ }
+ }
+
+ default:
+ doDecode = true;
+ }
+
+ if ( doDecode ) {
+
+ nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev );
+ if ( nBytes > 0 ) {
+ // The ALSA sequencer has a maximum buffer size for MIDI sysex
+ // events of 256 bytes. If a device sends sysex messages larger
+ // than this, they are segmented into 256 byte chunks. So,
+ // we'll watch for this and concatenate sysex chunks into a
+ // single sysex message if necessary.
+ if ( !continueSysex )
+ message.bytes.assign( buffer, &buffer[nBytes] );
+ else
+ message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] );
+
+ continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) );
+ if ( !continueSysex ) {
+
+ // Calculate the time stamp:
+ message.timeStamp = 0.0;
+
+ // Method 1: Use the system time.
+ //(void)gettimeofday(&tv, (struct timezone *)NULL);
+ //time = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ // Method 2: Use the ALSA sequencer event time data.
+ // (thanks to Pedro Lopez-Cabanillas!).
+ time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 );
+ lastTime = time;
+ time -= apiData->lastTime;
+ apiData->lastTime = lastTime;
+ if ( data->firstMessage == true )
+ data->firstMessage = false;
+ else
+ message.timeStamp = time * 0.000001;
+ }
+ else {
+#if defined(__RTMIDI_DEBUG__)
+ std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n";
+#endif
+ }
+ }
+ }
+
+ snd_seq_free_event( ev );
+ if ( message.bytes.size() == 0 || continueSysex ) continue;
+
+ if ( data->usingCallback ) {
+ RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+ callback( message.timeStamp, &message.bytes, data->userData );
+ }
+ else {
+ // As long as we haven't reached our queue size limit, push the message.
+ if ( data->queue.size < data->queue.ringSize ) {
+ data->queue.ring[data->queue.back++] = message;
+ if ( data->queue.back == data->queue.ringSize )
+ data->queue.back = 0;
+ data->queue.size++;
+ }
+ else
+ std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n";
+ }
+ }
+
+ if ( buffer ) free( buffer );
+ snd_midi_event_free( apiData->coder );
+ apiData->coder = 0;
+ apiData->thread = apiData->dummy_thread_id;
+ return 0;
+}
+
+MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )
+{
+ initialize( clientName );
+}
+
+MidiInAlsa :: ~MidiInAlsa()
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Shutdown the input thread.
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( inputData_.doInput ) {
+ inputData_.doInput = false;
+ int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) );
+ (void) res;
+ if ( !pthread_equal(data->thread, data->dummy_thread_id) )
+ pthread_join( data->thread, NULL );
+ }
+
+ // Cleanup.
+ close ( data->trigger_fds[0] );
+ close ( data->trigger_fds[1] );
+ if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_free_queue( data->seq, data->queue_id );
+#endif
+ freeSequencer();
+ delete data;
+}
+
+void MidiInAlsa :: initialize( const std::string& clientName )
+{
+ snd_seq_t* seq = createSequencer( clientName );
+ if ( seq == NULL ) {
+ s_seq = NULL;
+ errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;
+ data->seq = seq;
+ data->portNum = -1;
+ data->vport = -1;
+ data->subscription = 0;
+ data->dummy_thread_id = pthread_self();
+ data->thread = data->dummy_thread_id;
+ data->trigger_fds[0] = -1;
+ data->trigger_fds[1] = -1;
+ apiData_ = (void *) data;
+ inputData_.apiData = (void *) data;
+
+ if ( pipe(data->trigger_fds) == -1 ) {
+ errorString_ = "MidiInAlsa::initialize: error creating pipe objects.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Create the input queue
+#ifndef AVOID_TIMESTAMPING
+ data->queue_id = snd_seq_alloc_named_queue(s_seq, "RtMidi Queue");
+ // Set arbitrary tempo (mm=100) and resolution (240)
+ snd_seq_queue_tempo_t *qtempo;
+ snd_seq_queue_tempo_alloca(&qtempo);
+ snd_seq_queue_tempo_set_tempo(qtempo, 600000);
+ snd_seq_queue_tempo_set_ppq(qtempo, 240);
+ snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo);
+ snd_seq_drain_output(data->seq);
+#endif
+}
+
+// This function is used to count or get the pinfo structure for a given port number.
+unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber )
+{
+ snd_seq_client_info_t *cinfo;
+ int client;
+ int count = 0;
+ snd_seq_client_info_alloca( &cinfo );
+
+ snd_seq_client_info_set_client( cinfo, -1 );
+ while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) {
+ client = snd_seq_client_info_get_client( cinfo );
+ if ( client == 0 ) continue;
+ // Reset query info
+ snd_seq_port_info_set_client( pinfo, client );
+ snd_seq_port_info_set_port( pinfo, -1 );
+ while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) {
+ unsigned int atyp = snd_seq_port_info_get_type( pinfo );
+ if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue;
+ unsigned int caps = snd_seq_port_info_get_capability( pinfo );
+ if ( ( caps & type ) != type ) continue;
+ if ( count == portNumber ) return 1;
+ ++count;
+ }
+ }
+
+ // If a negative portNumber was used, return the port count.
+ if ( portNumber < 0 ) return count;
+ return 0;
+}
+
+unsigned int MidiInAlsa :: getPortCount()
+{
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+
+ AlsaMidiData *data = static_cast (apiData_);
+ return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 );
+}
+
+std::string MidiInAlsa :: getPortName( unsigned int portNumber )
+{
+ snd_seq_client_info_t *cinfo;
+ snd_seq_port_info_t *pinfo;
+ snd_seq_client_info_alloca( &cinfo );
+ snd_seq_port_info_alloca( &pinfo );
+
+ std::string stringName;
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) {
+ int cnum = snd_seq_port_info_get_client( pinfo );
+ snd_seq_get_any_client_info( data->seq, cnum, cinfo );
+ std::ostringstream os;
+ os << snd_seq_client_info_get_name( cinfo );
+ os << " "; // GO: These lines added to make sure devices are listed
+ os << snd_seq_port_info_get_client( pinfo ); // GO: with full portnames added to ensure individual device names
+ os << ":";
+ os << snd_seq_port_info_get_port( pinfo );
+ stringName = os.str();
+ return stringName;
+ }
+
+ // If we get here, we didn't find a match.
+ errorString_ = "MidiInAlsa::getPortName: error looking for port name!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return stringName;
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+}
+
+void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiInAlsa::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nSrc = this->getPortCount();
+ if (nSrc < 1) {
+ errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+ std::ostringstream ost;
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) {
+ ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+
+ snd_seq_addr_t sender, receiver;
+ sender.client = snd_seq_port_info_get_client( pinfo );
+ sender.port = snd_seq_port_info_get_port( pinfo );
+ receiver.client = snd_seq_client_id( data->seq );
+ if ( data->vport < 0 ) {
+ snd_seq_port_info_set_client( pinfo, 0 );
+ snd_seq_port_info_set_port( pinfo, 0 );
+ snd_seq_port_info_set_capability( pinfo,
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_SUBS_WRITE );
+ snd_seq_port_info_set_type( pinfo,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION );
+ snd_seq_port_info_set_midi_channels(pinfo, 16);
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_port_info_set_timestamping(pinfo, 1);
+ snd_seq_port_info_set_timestamp_real(pinfo, 1);
+ snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);
+#endif
+ snd_seq_port_info_set_name(pinfo, portName.c_str() );
+ data->vport = snd_seq_create_port(data->seq, pinfo);
+
+ if ( data->vport < 0 ) {
+ errorString_ = "MidiInAlsa::openPort: ALSA error creating input port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ receiver.port = data->vport;
+
+ if ( !data->subscription ) {
+ // Make subscription
+ if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) {
+ errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ snd_seq_port_subscribe_set_sender(data->subscription, &sender);
+ snd_seq_port_subscribe_set_dest(data->subscription, &receiver);
+ if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {
+ snd_seq_port_subscribe_free( data->subscription );
+ data->subscription = 0;
+ errorString_ = "MidiInAlsa::openPort: ALSA error making port connection.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ if ( inputData_.doInput == false ) {
+ // Start the input queue
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_start_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
+#endif
+ // Start our MIDI input thread.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
+
+ inputData_.doInput = true;
+ int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
+ pthread_attr_destroy(&attr);
+ if ( err ) {
+ snd_seq_unsubscribe_port( data->seq, data->subscription );
+ snd_seq_port_subscribe_free( data->subscription );
+ data->subscription = 0;
+ inputData_.doInput = false;
+ errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!";
+ RtMidi::error( RtError::THREAD_ERROR, errorString_ );
+ }
+ }
+
+ connected_ = true;
+}
+
+void MidiInAlsa :: openVirtualPort( std::string portName )
+{
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( data->vport < 0 ) {
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+ snd_seq_port_info_set_capability( pinfo,
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_SUBS_WRITE );
+ snd_seq_port_info_set_type( pinfo,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION );
+ snd_seq_port_info_set_midi_channels(pinfo, 16);
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_port_info_set_timestamping(pinfo, 1);
+ snd_seq_port_info_set_timestamp_real(pinfo, 1);
+ snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);
+#endif
+ snd_seq_port_info_set_name(pinfo, portName.c_str());
+ data->vport = snd_seq_create_port(data->seq, pinfo);
+
+ if ( data->vport < 0 ) {
+ errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ if ( inputData_.doInput == false ) {
+ // Wait for old thread to stop, if still running
+ if ( !pthread_equal(data->thread, data->dummy_thread_id) )
+ pthread_join( data->thread, NULL );
+
+ // Start the input queue
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_start_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
+#endif
+ // Start our MIDI input thread.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
+
+ inputData_.doInput = true;
+ int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
+ pthread_attr_destroy(&attr);
+ if ( err ) {
+ if ( data->subscription ) {
+ snd_seq_unsubscribe_port( data->seq, data->subscription );
+ snd_seq_port_subscribe_free( data->subscription );
+ data->subscription = 0;
+ }
+ inputData_.doInput = false;
+ errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!";
+ RtMidi::error( RtError::THREAD_ERROR, errorString_ );
+ }
+ }
+}
+
+void MidiInAlsa :: closePort( void )
+{
+ AlsaMidiData *data = static_cast (apiData_);
+
+ if ( connected_ ) {
+ if ( data->subscription ) {
+ snd_seq_unsubscribe_port( data->seq, data->subscription );
+ snd_seq_port_subscribe_free( data->subscription );
+ data->subscription = 0;
+ }
+ // Stop the input queue
+#ifndef AVOID_TIMESTAMPING
+ snd_seq_stop_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
+#endif
+ connected_ = false;
+ }
+
+ // Stop thread to avoid triggering the callback, while the port is intended to be closed
+ if ( inputData_.doInput ) {
+ inputData_.doInput = false;
+ int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) );
+ (void) res;
+ if ( !pthread_equal(data->thread, data->dummy_thread_id) )
+ pthread_join( data->thread, NULL );
+ }
+}
+
+//*********************************************************************//
+// API: LINUX ALSA
+// Class Definitions: MidiOutAlsa
+//*********************************************************************//
+
+MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi()
+{
+ initialize( clientName );
+}
+
+MidiOutAlsa :: ~MidiOutAlsa()
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );
+ if ( data->coder ) snd_midi_event_free( data->coder );
+ if ( data->buffer ) free( data->buffer );
+ freeSequencer();
+ delete data;
+}
+
+void MidiOutAlsa :: initialize( const std::string& clientName )
+{
+ snd_seq_t* seq = createSequencer( clientName );
+ if ( seq == NULL ) {
+ s_seq = NULL;
+ errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;
+ data->seq = seq;
+ data->portNum = -1;
+ data->vport = -1;
+ data->bufferSize = 32;
+ data->coder = 0;
+ data->buffer = 0;
+ int result = snd_midi_event_new( data->bufferSize, &data->coder );
+ if ( result < 0 ) {
+ delete data;
+ errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ data->buffer = (unsigned char *) malloc( data->bufferSize );
+ if ( data->buffer == NULL ) {
+ delete data;
+ errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n";
+ RtMidi::error( RtError::MEMORY_ERROR, errorString_ );
+ }
+ snd_midi_event_init( data->coder );
+ apiData_ = (void *) data;
+}
+
+unsigned int MidiOutAlsa :: getPortCount()
+{
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+
+ AlsaMidiData *data = static_cast (apiData_);
+ return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 );
+}
+
+std::string MidiOutAlsa :: getPortName( unsigned int portNumber )
+{
+ snd_seq_client_info_t *cinfo;
+ snd_seq_port_info_t *pinfo;
+ snd_seq_client_info_alloca( &cinfo );
+ snd_seq_port_info_alloca( &pinfo );
+
+ std::string stringName;
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) {
+ int cnum = snd_seq_port_info_get_client(pinfo);
+ snd_seq_get_any_client_info( data->seq, cnum, cinfo );
+ std::ostringstream os;
+ os << snd_seq_client_info_get_name(cinfo);
+ os << ":";
+ os << snd_seq_port_info_get_port(pinfo);
+ stringName = os.str();
+ return stringName;
+ }
+
+ // If we get here, we didn't find a match.
+ errorString_ = "MidiOutAlsa::getPortName: error looking for port name!";
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return stringName;
+}
+
+void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nSrc = this->getPortCount();
+ if (nSrc < 1) {
+ errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+ std::ostringstream ost;
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) {
+ ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ snd_seq_addr_t sender, receiver;
+ receiver.client = snd_seq_port_info_get_client( pinfo );
+ receiver.port = snd_seq_port_info_get_port( pinfo );
+ sender.client = snd_seq_client_id( data->seq );
+
+ if ( data->vport < 0 ) {
+ data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(),
+ SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION );
+ if ( data->vport < 0 ) {
+ errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ sender.port = data->vport;
+
+ // Make subscription
+ if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) {
+ snd_seq_port_subscribe_free( data->subscription );
+ errorString_ = "MidiOutAlsa::openPort: error allocation port subscribtion.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ snd_seq_port_subscribe_set_sender(data->subscription, &sender);
+ snd_seq_port_subscribe_set_dest(data->subscription, &receiver);
+ snd_seq_port_subscribe_set_time_update(data->subscription, 1);
+ snd_seq_port_subscribe_set_time_real(data->subscription, 1);
+ if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {
+ snd_seq_port_subscribe_free( data->subscription );
+ errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ connected_ = true;
+}
+
+void MidiOutAlsa :: closePort( void )
+{
+ if ( connected_ ) {
+ AlsaMidiData *data = static_cast (apiData_);
+ snd_seq_unsubscribe_port( data->seq, data->subscription );
+ snd_seq_port_subscribe_free( data->subscription );
+ connected_ = false;
+ }
+}
+
+void MidiOutAlsa :: openVirtualPort( std::string portName )
+{
+ AlsaMidiData *data = static_cast (apiData_);
+ if ( data->vport < 0 ) {
+ data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(),
+ SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION );
+
+ if ( data->vport < 0 ) {
+ errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+}
+
+void MidiOutAlsa :: sendMessage( std::vector *message )
+{
+ int result;
+ AlsaMidiData *data = static_cast (apiData_);
+ unsigned int nBytes = message->size();
+ if ( nBytes > data->bufferSize ) {
+ data->bufferSize = nBytes;
+ result = snd_midi_event_resize_buffer ( data->coder, nBytes);
+ if ( result != 0 ) {
+ errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ free (data->buffer);
+ data->buffer = (unsigned char *) malloc( data->bufferSize );
+ if ( data->buffer == NULL ) {
+ errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n";
+ RtMidi::error( RtError::MEMORY_ERROR, errorString_ );
+ }
+ }
+
+ snd_seq_event_t ev;
+ snd_seq_ev_clear(&ev);
+ snd_seq_ev_set_source(&ev, data->vport);
+ snd_seq_ev_set_subs(&ev);
+ snd_seq_ev_set_direct(&ev);
+ for ( unsigned int i=0; ibuffer[i] = message->at(i);
+ result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev );
+ if ( result < (int)nBytes ) {
+ errorString_ = "MidiOutAlsa::sendMessage: event parsing error!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ // Send the event.
+ result = snd_seq_event_output(data->seq, &ev);
+ if ( result < 0 ) {
+ errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+ snd_seq_drain_output(data->seq);
+}
+
+#endif // __LINUX_ALSA__
+
+
+//*********************************************************************//
+// API: Windows Multimedia Library (MM)
+//*********************************************************************//
+
+// API information deciphered from:
+// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp
+
+// Thanks to Jean-Baptiste Berruchon for the sysex code.
+
+#if defined(__WINDOWS_MM__)
+
+// The Windows MM API is based on the use of a callback function for
+// MIDI input. We convert the system specific time stamps to delta
+// time values.
+
+// Windows MM MIDI header files.
+#include
+#include
+
+#define RT_SYSEX_BUFFER_SIZE 1024
+#define RT_SYSEX_BUFFER_COUNT 4
+
+// A structure to hold variables related to the CoreMIDI API
+// implementation.
+struct WinMidiData {
+ HMIDIIN inHandle; // Handle to Midi Input Device
+ HMIDIOUT outHandle; // Handle to Midi Output Device
+ DWORD lastTime;
+ MidiInApi::MidiMessage message;
+ LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT];
+};
+
+//*********************************************************************//
+// API: Windows MM
+// Class Definitions: MidiInWinMM
+//*********************************************************************//
+
+static void CALLBACK midiInputCallback( HMIDIIN hmin,
+ UINT inputStatus,
+ DWORD_PTR instancePtr,
+ DWORD_PTR midiMessage,
+ DWORD timestamp )
+{
+ if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return;
+
+ //MidiInApi::RtMidiInData *data = static_cast (instancePtr);
+ MidiInApi::RtMidiInData *data = (MidiInApi::RtMidiInData *)instancePtr;
+ WinMidiData *apiData = static_cast (data->apiData);
+
+ // Calculate time stamp.
+ if ( data->firstMessage == true ) {
+ apiData->message.timeStamp = 0.0;
+ data->firstMessage = false;
+ }
+ else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;
+ apiData->lastTime = timestamp;
+
+ if ( inputStatus == MIM_DATA ) { // Channel or system message
+
+ // Make sure the first byte is a status byte.
+ unsigned char status = (unsigned char) (midiMessage & 0x000000FF);
+ if ( !(status & 0x80) ) return;
+
+ // Determine the number of bytes in the MIDI message.
+ unsigned short nBytes = 1;
+ if ( status < 0xC0 ) nBytes = 3;
+ else if ( status < 0xE0 ) nBytes = 2;
+ else if ( status < 0xF0 ) nBytes = 3;
+ else if ( status == 0xF1 ) {
+ if ( data->ignoreFlags & 0x02 ) return;
+ else nBytes = 2;
+ }
+ else if ( status == 0xF2 ) nBytes = 3;
+ else if ( status == 0xF3 ) nBytes = 2;
+ else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) {
+ // A MIDI timing tick message and we're ignoring it.
+ return;
+ }
+ else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
+ // A MIDI active sensing message and we're ignoring it.
+ return;
+ }
+
+ // Copy bytes to our MIDI message.
+ unsigned char *ptr = (unsigned char *) &midiMessage;
+ for ( int i=0; imessage.bytes.push_back( *ptr++ );
+ }
+ else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR )
+ MIDIHDR *sysex = ( MIDIHDR *) midiMessage;
+ if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) {
+ // Sysex message and we're not ignoring it
+ for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i )
+ apiData->message.bytes.push_back( sysex->lpData[i] );
+ }
+
+ // The WinMM API requires that the sysex buffer be requeued after
+ // input of each sysex message. Even if we are ignoring sysex
+ // messages, we still need to requeue the buffer in case the user
+ // decides to not ignore sysex messages in the future. However,
+ // it seems that WinMM calls this function with an empty sysex
+ // buffer when an application closes and in this case, we should
+ // avoid requeueing it, else the computer suddenly reboots after
+ // one or two minutes.
+ if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) {
+ //if ( sysex->dwBytesRecorded > 0 ) {
+ MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) );
+ if ( result != MMSYSERR_NOERROR )
+ std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n";
+
+ if ( data->ignoreFlags & 0x01 ) return;
+ }
+ else return;
+ }
+
+ if ( data->usingCallback ) {
+ RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+ callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );
+ }
+ else {
+ // As long as we haven't reached our queue size limit, push the message.
+ if ( data->queue.size < data->queue.ringSize ) {
+ data->queue.ring[data->queue.back++] = apiData->message;
+ if ( data->queue.back == data->queue.ringSize )
+ data->queue.back = 0;
+ data->queue.size++;
+ }
+ else
+ std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+ }
+
+ // Clear the vector for the next input message.
+ apiData->message.bytes.clear();
+}
+
+MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )
+{
+ initialize( clientName );
+}
+
+MidiInWinMM :: ~MidiInWinMM()
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ WinMidiData *data = static_cast (apiData_);
+ delete data;
+}
+
+void MidiInWinMM :: initialize( const std::string& /*clientName*/ )
+{
+ // We'll issue a warning here if no devices are available but not
+ // throw an error since the user can plugin something later.
+ unsigned int nDevices = midiInGetNumDevs();
+ if ( nDevices == 0 ) {
+ errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ WinMidiData *data = (WinMidiData *) new WinMidiData;
+ apiData_ = (void *) data;
+ inputData_.apiData = (void *) data;
+ data->message.bytes.clear(); // needs to be empty for first input message
+}
+
+void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiInWinMM::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nDevices = midiInGetNumDevs();
+ if (nDevices == 0) {
+ errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ std::ostringstream ost;
+ if ( portNumber >= nDevices ) {
+ ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ WinMidiData *data = static_cast (apiData_);
+ MMRESULT result = midiInOpen( &data->inHandle,
+ portNumber,
+ (DWORD_PTR)&midiInputCallback,
+ (DWORD_PTR)&inputData_,
+ CALLBACK_FUNCTION );
+ if ( result != MMSYSERR_NOERROR ) {
+ errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Allocate and init the sysex buffers.
+ for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ];
+ data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ];
+ data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE;
+ data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator
+ data->sysexBuffer[i]->dwFlags = 0;
+
+ result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
+ if ( result != MMSYSERR_NOERROR ) {
+ midiInClose( data->inHandle );
+ errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader).";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Register the buffer.
+ result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
+ if ( result != MMSYSERR_NOERROR ) {
+ midiInClose( data->inHandle );
+ errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer).";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ result = midiInStart( data->inHandle );
+ if ( result != MMSYSERR_NOERROR ) {
+ midiInClose( data->inHandle );
+ errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ connected_ = true;
+}
+
+void MidiInWinMM :: openVirtualPort( std::string portName )
+{
+ // This function cannot be implemented for the Windows MM MIDI API.
+ errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+}
+
+void MidiInWinMM :: closePort( void )
+{
+ if ( connected_ ) {
+ WinMidiData *data = static_cast (apiData_);
+ midiInReset( data->inHandle );
+ midiInStop( data->inHandle );
+
+ for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR));
+ delete [] data->sysexBuffer[i]->lpData;
+ delete [] data->sysexBuffer[i];
+ if ( result != MMSYSERR_NOERROR ) {
+ midiInClose( data->inHandle );
+ errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader).";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+
+ midiInClose( data->inHandle );
+ connected_ = false;
+ }
+}
+
+unsigned int MidiInWinMM :: getPortCount()
+{
+ return midiInGetNumDevs();
+}
+
+std::string MidiInWinMM :: getPortName( unsigned int portNumber )
+{
+ std::string stringName;
+ unsigned int nDevices = midiInGetNumDevs();
+ if ( portNumber >= nDevices ) {
+ std::ostringstream ost;
+ ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return stringName;
+ }
+
+ MIDIINCAPS deviceCaps;
+ midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS));
+
+#if defined( UNICODE ) || defined( _UNICODE )
+ int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);
+ stringName.assign( length, 0 );
+ length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);
+#else
+ stringName = std::string( deviceCaps.szPname );
+#endif
+
+ // Next lines added to add the portNumber to the name so that
+ // the device's names are sure to be listed with individual names
+ // even when they have the same brand name
+ std::ostringstream os;
+ os << " ";
+ os << portNumber;
+ stringName += os.str();
+
+ return stringName;
+}
+
+//*********************************************************************//
+// API: Windows MM
+// Class Definitions: MidiOutWinMM
+//*********************************************************************//
+
+MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi()
+{
+ initialize( clientName );
+}
+
+MidiOutWinMM :: ~MidiOutWinMM()
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ WinMidiData *data = static_cast (apiData_);
+ delete data;
+}
+
+void MidiOutWinMM :: initialize( const std::string& /*clientName*/ )
+{
+ // We'll issue a warning here if no devices are available but not
+ // throw an error since the user can plug something in later.
+ unsigned int nDevices = midiOutGetNumDevs();
+ if ( nDevices == 0 ) {
+ errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available.";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ // Save our api-specific connection information.
+ WinMidiData *data = (WinMidiData *) new WinMidiData;
+ apiData_ = (void *) data;
+}
+
+unsigned int MidiOutWinMM :: getPortCount()
+{
+ return midiOutGetNumDevs();
+}
+
+std::string MidiOutWinMM :: getPortName( unsigned int portNumber )
+{
+ std::string stringName;
+ unsigned int nDevices = midiOutGetNumDevs();
+ if ( portNumber >= nDevices ) {
+ std::ostringstream ost;
+ ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return stringName;
+ }
+
+ MIDIOUTCAPS deviceCaps;
+ midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));
+
+#if defined( UNICODE ) || defined( _UNICODE )
+ int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);
+ stringName.assign( length, 0 );
+ length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);
+#else
+ stringName = std::string( deviceCaps.szPname );
+#endif
+
+ return stringName;
+}
+
+void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ )
+{
+ if ( connected_ ) {
+ errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ unsigned int nDevices = midiOutGetNumDevs();
+ if (nDevices < 1) {
+ errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!";
+ RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );
+ }
+
+ std::ostringstream ost;
+ if ( portNumber >= nDevices ) {
+ ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );
+ }
+
+ WinMidiData *data = static_cast (apiData_);
+ MMRESULT result = midiOutOpen( &data->outHandle,
+ portNumber,
+ (DWORD)NULL,
+ (DWORD)NULL,
+ CALLBACK_NULL );
+ if ( result != MMSYSERR_NOERROR ) {
+ errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ connected_ = true;
+}
+
+void MidiOutWinMM :: closePort( void )
+{
+ if ( connected_ ) {
+ WinMidiData *data = static_cast (apiData_);
+ midiOutReset( data->outHandle );
+ midiOutClose( data->outHandle );
+ connected_ = false;
+ }
+}
+
+void MidiOutWinMM :: openVirtualPort( std::string portName )
+{
+ // This function cannot be implemented for the Windows MM MIDI API.
+ errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+}
+
+void MidiOutWinMM :: sendMessage( std::vector *message )
+{
+ unsigned int nBytes = static_cast(message->size());
+ if ( nBytes == 0 ) {
+ errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ MMRESULT result;
+ WinMidiData *data = static_cast (apiData_);
+ if ( message->at(0) == 0xF0 ) { // Sysex message
+
+ // Allocate buffer for sysex data.
+ char *buffer = (char *) malloc( nBytes );
+ if ( buffer == NULL ) {
+ errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!";
+ RtMidi::error( RtError::MEMORY_ERROR, errorString_ );
+ }
+
+ // Copy data to buffer.
+ for ( unsigned int i=0; iat(i);
+
+ // Create and prepare MIDIHDR structure.
+ MIDIHDR sysex;
+ sysex.lpData = (LPSTR) buffer;
+ sysex.dwBufferLength = nBytes;
+ sysex.dwFlags = 0;
+ result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) );
+ if ( result != MMSYSERR_NOERROR ) {
+ free( buffer );
+ errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Send the message.
+ result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) );
+ if ( result != MMSYSERR_NOERROR ) {
+ free( buffer );
+ errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+
+ // Unprepare the buffer and MIDIHDR.
+ while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 );
+ free( buffer );
+
+ }
+ else { // Channel or system message.
+
+ // Make sure the message size isn't too big.
+ if ( nBytes > 3 ) {
+ errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+ return;
+ }
+
+ // Pack MIDI bytes into double word.
+ DWORD packet;
+ unsigned char *ptr = (unsigned char *) &packet;
+ for ( unsigned int i=0; iat(i);
+ ++ptr;
+ }
+
+ // Send the message immediately.
+ result = midiOutShortMsg( data->outHandle, packet );
+ if ( result != MMSYSERR_NOERROR ) {
+ errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message.";
+ RtMidi::error( RtError::DRIVER_ERROR, errorString_ );
+ }
+ }
+}
+
+#endif // __WINDOWS_MM__
+
+// *********************************************************************//
+// API: WINDOWS Kernel Streaming
+//
+// Written by Sebastien Alaiwan, 2012.
+//
+// NOTE BY GARY: much of the KS-specific code below probably should go in a separate file.
+//
+// *********************************************************************//
+
+#if defined(__WINDOWS_KS__)
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ks.h"
+#include "ksmedia.h"
+
+#define INSTANTIATE_GUID(a) GUID const a = { STATIC_ ## a }
+
+INSTANTIATE_GUID(GUID_NULL);
+INSTANTIATE_GUID(KSPROPSETID_Pin);
+INSTANTIATE_GUID(KSPROPSETID_Connection);
+INSTANTIATE_GUID(KSPROPSETID_Topology);
+INSTANTIATE_GUID(KSINTERFACESETID_Standard);
+INSTANTIATE_GUID(KSMEDIUMSETID_Standard);
+INSTANTIATE_GUID(KSDATAFORMAT_TYPE_MUSIC);
+INSTANTIATE_GUID(KSDATAFORMAT_SUBTYPE_MIDI);
+INSTANTIATE_GUID(KSDATAFORMAT_SPECIFIER_NONE);
+
+#undef INSTANTIATE_GUID
+
+typedef std::basic_string tstring;
+
+inline bool IsValid(HANDLE handle)
+{
+ return handle != NULL && handle != INVALID_HANDLE_VALUE;
+}
+
+class ComException : public std::runtime_error
+{
+private:
+ static std::string MakeString(std::string const& s, HRESULT hr)
+ {
+ std::stringstream ss;
+ ss << "(error 0x" << std::hex << hr << ")";
+ return s + ss.str();
+ }
+
+public:
+ ComException(std::string const& s, HRESULT hr) :
+ std::runtime_error(MakeString(s, hr))
+ {
+ }
+};
+
+template
+class CKsEnumFilters
+{
+public:
+ ~CKsEnumFilters()
+ {
+ DestroyLists();
+ }
+
+ void EnumFilters(GUID const* categories, size_t numCategories)
+ {
+ DestroyLists();
+
+ if (categories == 0)
+ {
+ printf ("Error: CKsEnumFilters: invalid argument\n");
+ assert(0);
+ }
+ // Get a handle to the device set specified by the guid
+ HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&categories[0], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (!IsValid(hDevInfo))
+ {
+ printf ("Error: CKsEnumFilters: no devices found");
+ assert (0);
+ }
+
+ // Loop through members of the set and get details for each
+ for (int iClassMember=0;;iClassMember++) {
+ {
+ SP_DEVICE_INTERFACE_DATA DID;
+ DID.cbSize = sizeof(DID);
+ DID.Reserved = 0;
+
+ bool fRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &categories[0], iClassMember, &DID);
+ if (!fRes)
+ break;
+
+ // Get filter friendly name
+ HKEY hRegKey = ::SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &DID, 0, KEY_READ);
+ if (hRegKey == INVALID_HANDLE_VALUE)
+ {
+ assert(0);
+ printf "CKsEnumFilters: interface has no registry\n");
+ }
+ char friendlyName[256];
+ DWORD dwSize = sizeof friendlyName;
+ LONG lval = ::RegQueryValueEx(hRegKey, TEXT("FriendlyName"), NULL, NULL, (LPBYTE)friendlyName, &dwSize);
+ ::RegCloseKey(hRegKey);
+ if (lval != ERROR_SUCCESS)
+ {
+ assert(0);
+ printf ("CKsEnumFilters: interface has no friendly name");
+ }
+ // Get details for the device registered in this class
+ DWORD const cbItfDetails = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
+ std::vector buffer(cbItfDetails);
+
+ SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast(&buffer[0]);
+ pDevInterfaceDetails->cbSize = sizeof(*pDevInterfaceDetails);
+
+ SP_DEVINFO_DATA DevInfoData;
+ DevInfoData.cbSize = sizeof(DevInfoData);
+ DevInfoData.Reserved = 0;
+
+ fRes = ::SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, cbItfDetails, NULL, &DevInfoData);
+ if (!fRes)
+ {
+ printf("CKsEnumFilters: could not get interface details");
+ assert(0);
+ }
+ // check additional category guids which may (or may not) have been supplied
+ for (size_t i=1; i < numCategories; ++i) {
+ SP_DEVICE_INTERFACE_DATA DIDAlias;
+ DIDAlias.cbSize = sizeof(DIDAlias);
+ DIDAlias.Reserved = 0;
+
+ fRes = ::SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &categories[i], &DIDAlias);
+ if (!fRes)
+ {
+ printf("CKsEnumFilters: could not get interface alias");
+ assert(0);
+ }
+ // Check if the this interface alias is enabled.
+ if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED))
+ {
+ printf("CKsEnumFilters: interface alias is not enabled");
+ assert(0);
+ }
+ }
+
+ std::auto_ptr pFilter(new TFilterType(pDevInterfaceDetails->DevicePath, friendlyName));
+
+ pFilter->Instantiate();
+ pFilter->FindMidiPins();
+ pFilter->Validate();
+
+ m_Filters.push_back(pFilter.release());
+ }
+ }
+
+ ::SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
+private:
+ void DestroyLists()
+ {
+ for (size_t i=0;i < m_Filters.size();++i)
+ delete m_Filters[i];
+ m_Filters.clear();
+ }
+
+public:
+ // TODO: make this private.
+ std::vector m_Filters;
+};
+
+class CKsObject
+{
+public:
+ CKsObject(HANDLE handle) : m_handle(handle)
+ {
+ }
+
+protected:
+ HANDLE m_handle;
+
+ void SetProperty(REFGUID guidPropertySet, ULONG nProperty, void* pvValue, ULONG cbValue)
+ {
+ KSPROPERTY ksProperty;
+ memset(&ksProperty, 0, sizeof ksProperty);
+ ksProperty.Set = guidPropertySet;
+ ksProperty.Id = nProperty;
+ ksProperty.Flags = KSPROPERTY_TYPE_SET;
+
+ HRESULT hr = DeviceIoControlKsProperty(ksProperty, pvValue, cbValue);
+ if (FAILED(hr))
+ {
+ printf("CKsObject::SetProperty: could not set property");
+ exit(0);
+ }
+ }
+
+private:
+
+ HRESULT DeviceIoControlKsProperty(KSPROPERTY& ksProperty, void* pvValue, ULONG cbValue)
+ {
+ ULONG ulReturned;
+ return ::DeviceIoControl(
+ m_handle,
+ IOCTL_KS_PROPERTY,
+ &ksProperty,
+ sizeof(ksProperty),
+ pvValue,
+ cbValue,
+ &ulReturned,
+ NULL);
+ }
+};
+
+class CKsPin;
+
+class CKsFilter : public CKsObject
+{
+ friend class CKsPin;
+
+public:
+ CKsFilter(tstring const& name, std::string const& sFriendlyName);
+ virtual ~CKsFilter();
+
+ virtual void Instantiate();
+
+ template
+ T GetPinProperty(ULONG nPinId, ULONG nProperty)
+ {
+ ULONG ulReturned = 0;
+ T value;
+
+ KSP_PIN ksPProp;
+ ksPProp.Property.Set = KSPROPSETID_Pin;
+ ksPProp.Property.Id = nProperty;
+ ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
+ ksPProp.PinId = nPinId;
+ ksPProp.Reserved = 0;
+
+ HRESULT hr = ::DeviceIoControl(
+ m_handle,
+ IOCTL_KS_PROPERTY,
+ &ksPProp,
+ sizeof(KSP_PIN),
+ &value,
+ sizeof(value),
+ &ulReturned,
+ NULL);
+ if (FAILED(hr))
+ {
+ printf("CKsFilter::GetPinProperty: failed to retrieve property");
+ exit(0);
+ }
+
+ return value;
+ }
+
+ void GetPinPropertyMulti(ULONG nPinId, REFGUID guidPropertySet, ULONG nProperty, PKSMULTIPLE_ITEM* ppKsMultipleItem)
+ {
+ HRESULT hr;
+
+ KSP_PIN ksPProp;
+ ksPProp.Property.Set = guidPropertySet;
+ ksPProp.Property.Id = nProperty;
+ ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
+ ksPProp.PinId = nPinId;
+ ksPProp.Reserved = 0;
+
+ ULONG cbMultipleItem = 0;
+ hr = ::DeviceIoControl(m_handle,
+ IOCTL_KS_PROPERTY,
+ &ksPProp.Property,
+ sizeof(KSP_PIN),
+ NULL,
+ 0,
+ &cbMultipleItem,
+ NULL);
+ if (FAILED(hr))
+ {
+ printf("CKsFilter::GetPinPropertyMulti: cannot get property");
+ exit(0);
+ }
+
+ *ppKsMultipleItem = (PKSMULTIPLE_ITEM) new BYTE[cbMultipleItem];
+
+ ULONG ulReturned = 0;
+ hr = ::DeviceIoControl(
+ m_handle,
+ IOCTL_KS_PROPERTY,
+ &ksPProp,
+ sizeof(KSP_PIN),
+ (PVOID)*ppKsMultipleItem,
+ cbMultipleItem,
+ &ulReturned,
+ NULL);
+ if (FAILED(hr))
+ {
+ printf("CKsFilter::GetPinPropertyMulti: cannot get property");
+ exit(0);
+ }
+ }
+
+ std::string const& GetFriendlyName() const
+ {
+ return m_sFriendlyName;
+ }
+
+protected:
+
+ std::vector m_Pins; // this list owns the pins.
+
+ std::vector m_RenderPins;
+ std::vector m_CapturePins;
+
+private:
+ std::string const m_sFriendlyName; // friendly name eg "Virus TI Synth"
+ tstring const m_sName; // Filter path, eg "\\?\usb#vid_133e&pid_0815...\vtimidi02"
+};
+
+class CKsPin : public CKsObject
+{
+public:
+ CKsPin(CKsFilter* pFilter, ULONG nId);
+ virtual ~CKsPin();
+
+ virtual void Instantiate();
+
+ void ClosePin();
+
+ void SetState(KSSTATE ksState);
+
+ void WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED);
+ void ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED);
+
+ KSPIN_DATAFLOW GetDataFlow() const
+ {
+ return m_DataFlow;
+ }
+
+ bool IsSink() const
+ {
+ return m_Communication == KSPIN_COMMUNICATION_SINK
+ || m_Communication == KSPIN_COMMUNICATION_BOTH;
+ }
+
+
+protected:
+ PKSPIN_CONNECT m_pKsPinConnect; // creation parameters of pin
+ CKsFilter* const m_pFilter;
+
+ ULONG m_cInterfaces;
+ PKSIDENTIFIER m_pInterfaces;
+ PKSMULTIPLE_ITEM m_pmiInterfaces;
+
+ ULONG m_cMediums;
+ PKSIDENTIFIER m_pMediums;
+ PKSMULTIPLE_ITEM m_pmiMediums;
+
+ ULONG m_cDataRanges;
+ PKSDATARANGE m_pDataRanges;
+ PKSMULTIPLE_ITEM m_pmiDataRanges;
+
+ KSPIN_DATAFLOW m_DataFlow;
+ KSPIN_COMMUNICATION m_Communication;
+};
+
+CKsFilter::CKsFilter(tstring const& sName, std::string const& sFriendlyName) :
+ CKsObject(INVALID_HANDLE_VALUE),
+ m_sFriendlyName(sFriendlyName),
+ m_sName(sName)
+{
+ if (sName.empty())
+ {
+ printf("CKsFilter::CKsFilter: name can't be empty");
+ assert(0);
+ }
+}
+
+CKsFilter::~CKsFilter()
+{
+ for (size_t i=0;i < m_Pins.size();++i)
+ delete m_Pins[i];
+
+ if (IsValid(m_handle))
+ ::CloseHandle(m_handle);
+}
+
+void CKsFilter::Instantiate()
+{
+ m_handle = CreateFile(
+ m_sName.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if (!IsValid(m_handle))
+ {
+ DWORD const dwError = GetLastError();
+ throw ComException("CKsFilter::Instantiate: can't open driver", HRESULT_FROM_WIN32(dwError));
+ }
+}
+
+CKsPin::CKsPin(CKsFilter* pFilter, ULONG PinId) :
+ CKsObject(INVALID_HANDLE_VALUE),
+ m_pKsPinConnect(NULL),
+ m_pFilter(pFilter)
+{
+ m_Communication = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_COMMUNICATION);
+ m_DataFlow = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_DATAFLOW);
+
+ // Interfaces
+ m_pFilter->GetPinPropertyMulti(
+ PinId,
+ KSPROPSETID_Pin,
+ KSPROPERTY_PIN_INTERFACES,
+ &m_pmiInterfaces);
+
+ m_cInterfaces = m_pmiInterfaces->Count;
+ m_pInterfaces = (PKSPIN_INTERFACE)(m_pmiInterfaces + 1);
+
+ // Mediums
+ m_pFilter->GetPinPropertyMulti(
+ PinId,
+ KSPROPSETID_Pin,
+ KSPROPERTY_PIN_MEDIUMS,
+ &m_pmiMediums);
+
+ m_cMediums = m_pmiMediums->Count;
+ m_pMediums = (PKSPIN_MEDIUM)(m_pmiMediums + 1);
+
+ // Data ranges
+ m_pFilter->GetPinPropertyMulti(
+ PinId,
+ KSPROPSETID_Pin,
+ KSPROPERTY_PIN_DATARANGES,
+ &m_pmiDataRanges);
+
+ m_cDataRanges = m_pmiDataRanges->Count;
+ m_pDataRanges = (PKSDATARANGE)(m_pmiDataRanges + 1);
+}
+
+CKsPin::~CKsPin()
+{
+ ClosePin();
+
+ delete[] (BYTE*)m_pKsPinConnect;
+ delete[] (BYTE*)m_pmiDataRanges;
+ delete[] (BYTE*)m_pmiInterfaces;
+ delete[] (BYTE*)m_pmiMediums;
+}
+
+void CKsPin::ClosePin()
+{
+ if (IsValid(m_handle)) {
+ SetState(KSSTATE_STOP);
+ ::CloseHandle(m_handle);
+ }
+ m_handle = INVALID_HANDLE_VALUE;
+}
+
+void CKsPin::SetState(KSSTATE ksState)
+{
+ SetProperty(KSPROPSETID_Connection, KSPROPERTY_CONNECTION_STATE, &ksState, sizeof(ksState));
+}
+
+void CKsPin::Instantiate()
+{
+ if (!m_pKsPinConnect)
+ {
+ printf("CKsPin::Instanciate: abstract pin");
+ assert(0);
+ }
+ DWORD const dwResult = KsCreatePin(m_pFilter->m_handle, m_pKsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_handle);
+ if (dwResult != ERROR_SUCCESS)
+ throw ComException("CKsMidiCapFilter::CreateRenderPin: Pin instanciation failed", HRESULT_FROM_WIN32(dwResult));
+}
+
+void CKsPin::WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED)
+{
+ DWORD cbWritten;
+ BOOL fRes = ::DeviceIoControl(
+ m_handle,
+ IOCTL_KS_WRITE_STREAM,
+ NULL,
+ 0,
+ pKSSTREAM_HEADER,
+ pKSSTREAM_HEADER->Size,
+ &cbWritten,
+ pOVERLAPPED);
+ if (!fRes) {
+ DWORD const dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ throw ComException("CKsPin::WriteData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError));
+ }
+}
+
+void CKsPin::ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED)
+{
+ DWORD cbReturned;
+ BOOL fRes = ::DeviceIoControl(
+ m_handle,
+ IOCTL_KS_READ_STREAM,
+ NULL,
+ 0,
+ pKSSTREAM_HEADER,
+ pKSSTREAM_HEADER->Size,
+ &cbReturned,
+ pOVERLAPPED);
+ if (!fRes) {
+ DWORD const dwError = GetLastError();
+ if (dwError != ERROR_IO_PENDING)
+ throw ComException("CKsPin::ReadData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError));
+ }
+}
+
+class CKsMidiFilter : public CKsFilter
+{
+public:
+ void FindMidiPins();
+
+protected:
+ CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName);
+};
+
+class CKsMidiPin : public CKsPin
+{
+public:
+ CKsMidiPin(CKsFilter* pFilter, ULONG nId);
+};
+
+class CKsMidiRenFilter : public CKsMidiFilter
+{
+public:
+ CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName);
+ CKsMidiPin* CreateRenderPin();
+
+ void Validate()
+ {
+ if (m_RenderPins.empty())
+ {
+ printf("Could not find a MIDI render pin");
+ assert(0);
+ }
+ }
+};
+
+class CKsMidiCapFilter : public CKsMidiFilter
+{
+public:
+ CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName);
+ CKsMidiPin* CreateCapturePin();
+
+ void Validate()
+ {
+ if (m_CapturePins.empty())
+ {
+ assert(0);
+ printf("Could not find a MIDI capture pin");
+ }
+ }
+};
+
+CKsMidiFilter::CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName) :
+ CKsFilter(sPath, sFriendlyName)
+{
+}
+
+void CKsMidiFilter::FindMidiPins()
+{
+ ULONG numPins = GetPinProperty(0, KSPROPERTY_PIN_CTYPES);
+
+ for (ULONG iPin = 0; iPin < numPins; ++iPin) {
+ {
+ KSPIN_COMMUNICATION com = GetPinProperty(iPin, KSPROPERTY_PIN_COMMUNICATION);
+ if (com != KSPIN_COMMUNICATION_SINK && com != KSPIN_COMMUNICATION_BOTH)
+ {
+ printf("Unknown pin communication value");
+ assert(0);
+ }
+
+ m_Pins.push_back(new CKsMidiPin(this, iPin));
+ }
+
+ }
+
+ m_RenderPins.clear();
+ m_CapturePins.clear();
+
+ for (size_t i = 0; i < m_Pins.size(); ++i) {
+ CKsPin* const pPin = m_Pins[i];
+
+ if (pPin->IsSink()) {
+ if (pPin->GetDataFlow() == KSPIN_DATAFLOW_IN)
+ m_RenderPins.push_back(pPin);
+ else
+ m_CapturePins.push_back(pPin);
+ }
+ }
+
+ if (m_RenderPins.empty() && m_CapturePins.empty())
+ {
+ printf("No valid pins found on the filter.");
+ assert(0);
+
+ }
+}
+
+CKsMidiRenFilter::CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName) :
+ CKsMidiFilter(sPath, sFriendlyName)
+{
+}
+
+CKsMidiPin* CKsMidiRenFilter::CreateRenderPin()
+{
+ if (m_RenderPins.empty())
+ {
+ printf("Could not find a MIDI render pin");
+ assert(0);
+ }
+
+ CKsMidiPin* pPin = (CKsMidiPin*)m_RenderPins[0];
+ pPin->Instantiate();
+ return pPin;
+}
+
+CKsMidiCapFilter::CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName) :
+ CKsMidiFilter(sPath, sFriendlyName)
+{
+}
+
+CKsMidiPin* CKsMidiCapFilter::CreateCapturePin()
+{
+ if (m_CapturePins.empty())
+ {
+ printf("Could not find a MIDI capture pin");
+ assert(0);
+ }
+ CKsMidiPin* pPin = (CKsMidiPin*)m_CapturePins[0];
+ pPin->Instantiate();
+ return pPin;
+}
+
+CKsMidiPin::CKsMidiPin(CKsFilter* pFilter, ULONG nId) :
+ CKsPin(pFilter, nId)
+{
+ DWORD const cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT);
+ m_pKsPinConnect = (PKSPIN_CONNECT) new BYTE[cbPinCreateSize];
+
+ m_pKsPinConnect->Interface.Set = KSINTERFACESETID_Standard;
+ m_pKsPinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
+ m_pKsPinConnect->Interface.Flags = 0;
+ m_pKsPinConnect->Medium.Set = KSMEDIUMSETID_Standard;
+ m_pKsPinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
+ m_pKsPinConnect->Medium.Flags = 0;
+ m_pKsPinConnect->PinId = nId;
+ m_pKsPinConnect->PinToHandle = NULL;
+ m_pKsPinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
+ m_pKsPinConnect->Priority.PrioritySubClass = 1;
+
+ // point m_pDataFormat to just after the pConnect struct
+ KSDATAFORMAT* m_pDataFormat = (KSDATAFORMAT*)(m_pKsPinConnect + 1);
+ m_pDataFormat->FormatSize = sizeof(KSDATAFORMAT);
+ m_pDataFormat->Flags = 0;
+ m_pDataFormat->SampleSize = 0;
+ m_pDataFormat->Reserved = 0;
+ m_pDataFormat->MajorFormat = GUID(KSDATAFORMAT_TYPE_MUSIC);
+ m_pDataFormat->SubFormat = GUID(KSDATAFORMAT_SUBTYPE_MIDI);
+ m_pDataFormat->Specifier = GUID(KSDATAFORMAT_SPECIFIER_NONE);
+
+ bool hasStdStreamingInterface = false;
+ bool hasStdStreamingMedium = false;
+
+ for ( ULONG i = 0; i < m_cInterfaces; i++ ) {
+ if (m_pInterfaces[i].Set == KSINTERFACESETID_Standard
+ && m_pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING)
+ hasStdStreamingInterface = true;
+ }
+
+ for (ULONG i = 0; i < m_cMediums; i++) {
+ if (m_pMediums[i].Set == KSMEDIUMSETID_Standard
+ && m_pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO)
+ hasStdStreamingMedium = true;
+ }
+
+ if (!hasStdStreamingInterface) // No standard streaming interfaces on the pin
+ {
+ printf("CKsMidiPin::CKsMidiPin: no standard streaming interface");
+ assert(0);
+ }
+
+ if (!hasStdStreamingMedium) // No standard streaming mediums on the pin
+ {
+ printf("CKsMidiPin::CKsMidiPin: no standard streaming medium")
+ assert(0);
+ };
+
+ bool hasMidiDataRange = false;
+
+ BYTE const* pDataRangePtr = reinterpret_cast(m_pDataRanges);
+
+ for (ULONG i = 0; i < m_cDataRanges; ++i) {
+ KSDATARANGE const* pDataRange = reinterpret_cast(pDataRangePtr);
+
+ if (pDataRange->SubFormat == KSDATAFORMAT_SUBTYPE_MIDI) {
+ hasMidiDataRange = true;
+ break;
+ }
+
+ pDataRangePtr += pDataRange->FormatSize;
+ }
+
+ if (!hasMidiDataRange) // No MIDI dataranges on the pin
+ {
+ printf("CKsMidiPin::CKsMidiPin: no MIDI datarange");
+ assert(0);
+ }
+}
+
+
+struct WindowsKsData
+{
+ WindowsKsData() : m_pPin(NULL), m_Buffer(1024), m_hInputThread(NULL)
+ {
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
+ m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ m_hInputThread = NULL;
+ }
+
+ ~WindowsKsData()
+ {
+ ::CloseHandle(overlapped.hEvent);
+ ::CloseHandle(m_hExitEvent);
+ }
+
+ OVERLAPPED overlapped;
+ CKsPin* m_pPin;
+ std::vector m_Buffer;
+ std::auto_ptr > m_pCaptureEnum;
+ std::auto_ptr > m_pRenderEnum;
+ HANDLE m_hInputThread;
+ HANDLE m_hExitEvent;
+};
+
+// *********************************************************************//
+// API: WINDOWS Kernel Streaming
+// Class Definitions: MidiInWinKS
+// *********************************************************************//
+
+DWORD WINAPI midiKsInputThread(VOID* pUser)
+{
+ MidiInApi::RtMidiInData* data = static_cast(pUser);
+ WindowsKsData* apiData = static_cast(data->apiData);
+
+ HANDLE hEvents[] = { apiData->overlapped.hEvent, apiData->m_hExitEvent };
+
+ while ( true ) {
+ KSSTREAM_HEADER packet;
+ memset(&packet, 0, sizeof packet);
+ packet.Size = sizeof(KSSTREAM_HEADER);
+ packet.PresentationTime.Time = 0;
+ packet.PresentationTime.Numerator = 1;
+ packet.PresentationTime.Denominator = 1;
+ packet.Data = &apiData->m_Buffer[0];
+ packet.DataUsed = 0;
+ packet.FrameExtent = apiData->m_Buffer.size();
+ apiData->m_pPin->ReadData(&packet, &apiData->overlapped);
+
+ DWORD dwRet = ::WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
+
+ if ( dwRet == WAIT_OBJECT_0 ) {
+ // parse packet
+ unsigned char* pData = (unsigned char*)packet.Data;
+ unsigned int iOffset = 0;
+
+ while ( iOffset < packet.DataUsed ) {
+ KSMUSICFORMAT* pMusic = (KSMUSICFORMAT*)&pData[iOffset];
+ iOffset += sizeof(KSMUSICFORMAT);
+
+ MidiInApi::MidiMessage message;
+ message.timeStamp = 0;
+ for(size_t i=0;i < pMusic->ByteCount;++i)
+ message.bytes.push_back(pData[iOffset+i]);
+
+ if ( data->usingCallback ) {
+ RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback)data->userCallback;
+ callback(message.timeStamp, &message.bytes, data->userData);
+ }
+ else {
+ // As long as we haven't reached our queue size limit, push the message.
+ if ( data->queue.size < data->queue.ringSize ) {
+ data->queue.ring[data->queue.back++] = message;
+ if(data->queue.back == data->queue.ringSize)
+ data->queue.back = 0;
+ data->queue.size++;
+ }
+ else
+ std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+ }
+
+ iOffset += pMusic->ByteCount;
+
+ // re-align on 32 bits
+ if ( iOffset % 4 != 0 )
+ iOffset += (4 - iOffset % 4);
+ }
+ }
+ else
+ break;
+ }
+ return 0;
+}
+
+MidiInWinKS :: MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )
+{
+ initialize( clientName );
+}
+
+void MidiInWinKS :: initialize( const std::string& clientName )
+{
+ WindowsKsData* data = new WindowsKsData;
+ apiData_ = (void*)data;
+ inputData_.apiData = data;
+
+ GUID const aguidEnumCats[] =
+ {
+ { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_CAPTURE }
+ };
+ data->m_pCaptureEnum.reset(new CKsEnumFilters );
+ data->m_pCaptureEnum->EnumFilters(aguidEnumCats, 2);
+}
+
+MidiInWinKS :: ~MidiInWinKS()
+{
+ WindowsKsData* data = static_cast(apiData_);
+ {
+ if ( data->m_pPin )
+ closePort();
+ }
+
+ delete data;
+}
+
+void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portName )
+{
+ WindowsKsData* data = static_cast(apiData_);
+
+ if ( portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size() ) {
+ std::stringstream ost;
+ ost << "MidiInWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber];
+ data->m_pPin = pFilter->CreateCapturePin();
+
+ if ( data->m_pPin == NULL ) {
+ std::stringstream ost;
+ ost << "MidiInWinKS::openPort: KS error opening port (could not create pin)";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ data->m_pPin->SetState(KSSTATE_RUN);
+
+ DWORD threadId;
+ data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId);
+ if ( data->m_hInputThread == NULL ) {
+ std::stringstream ost;
+ ost << "MidiInWinKS::initialize: Could not create input thread : Windows error " << GetLastError() << std::endl;;
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ connected_ = true;
+}
+
+void MidiInWinKS :: openVirtualPort( const std::string portName )
+{
+ // This function cannot be implemented for the Windows KS MIDI API.
+ errorString_ = "MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+}
+
+unsigned int MidiInWinKS :: getPortCount()
+{
+ WindowsKsData* data = static_cast(apiData_);
+ return (unsigned int)data->m_pCaptureEnum->m_Filters.size();
+}
+
+std::string MidiInWinKS :: getPortName(unsigned int portNumber)
+{
+ WindowsKsData* data = static_cast(apiData_);
+
+ if(portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) {
+ std::stringstream ost;
+ ost << "MidiInWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber];
+ return pFilter->GetFriendlyName();
+}
+
+void MidiInWinKS :: closePort()
+{
+ WindowsKsData* data = static_cast(apiData_);
+ connected_ = false;
+
+ if(data->m_hInputThread) {
+ ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE);
+ ::CloseHandle(data->m_hInputThread);
+ }
+
+ if(data->m_pPin) {
+ data->m_pPin->SetState(KSSTATE_PAUSE);
+ data->m_pPin->SetState(KSSTATE_STOP);
+ data->m_pPin->ClosePin();
+ data->m_pPin = NULL;
+ }
+}
+
+// *********************************************************************//
+// API: WINDOWS Kernel Streaming
+// Class Definitions: MidiOutWinKS
+// *********************************************************************//
+
+MidiOutWinKS :: MidiOutWinKS( const std::string clientName ) : MidiOutApi()
+{
+ initialize( clientName );
+}
+
+void MidiOutWinKS :: initialize( const std::string& clientName )
+{
+ WindowsKsData* data = new WindowsKsData;
+
+ data->m_pPin = NULL;
+ data->m_pRenderEnum.reset(new CKsEnumFilters );
+ GUID const aguidEnumCats[] =
+ {
+ { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_RENDER }
+ };
+ data->m_pRenderEnum->EnumFilters(aguidEnumCats, 2);
+
+ apiData_ = (void*)data;
+}
+
+MidiOutWinKS :: ~MidiOutWinKS()
+{
+ // Close a connection if it exists.
+ closePort();
+
+ // Cleanup.
+ WindowsKsData* data = static_cast(apiData_);
+ delete data;
+}
+
+void MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portName )
+{
+ WindowsKsData* data = static_cast(apiData_);
+
+ if(portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) {
+ std::stringstream ost;
+ ost << "MidiOutWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber];
+ data->m_pPin = pFilter->CreateRenderPin();
+
+ if(data->m_pPin == NULL) {
+ std::stringstream ost;
+ ost << "MidiOutWinKS::openPort: KS error opening port (could not create pin)";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ data->m_pPin->SetState(KSSTATE_RUN);
+ connected_ = true;
+}
+
+void MidiOutWinKS :: openVirtualPort( const std::string portName )
+{
+ // This function cannot be implemented for the Windows KS MIDI API.
+ errorString_ = "MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!";
+ RtMidi::error( RtError::WARNING, errorString_ );
+}
+
+unsigned int MidiOutWinKS :: getPortCount()
+{
+ WindowsKsData* data = static_cast(apiData_);
+
+ return (unsigned int)data->m_pRenderEnum->m_Filters.size();
+}
+
+std::string MidiOutWinKS :: getPortName( unsigned int portNumber )
+{
+ WindowsKsData* data = static_cast(apiData_);
+
+ if ( portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size() ) {
+ std::stringstream ost;
+ ost << "MidiOutWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber];
+ return pFilter->GetFriendlyName();
+}
+
+void MidiOutWinKS :: closePort()
+{
+ WindowsKsData* data = static_cast(apiData_);
+ connected_ = false;
+
+ if ( data->m_pPin ) {
+ data->m_pPin->SetState(KSSTATE_PAUSE);
+ data->m_pPin->SetState(KSSTATE_STOP);
+ data->m_pPin->ClosePin();
+ data->m_pPin = NULL;
+ }
+}
+
+void MidiOutWinKS :: sendMessage(std::vector* pMessage)
+{
+ std::vector const& msg = *pMessage;
+ WindowsKsData* data = static_cast(apiData_);
+ size_t iNumMidiBytes = msg.size();
+ size_t pos = 0;
+
+ // write header
+ KSMUSICFORMAT* pKsMusicFormat = reinterpret_cast(&data->m_Buffer[pos]);
+ pKsMusicFormat->TimeDeltaMs = 0;
+ pKsMusicFormat->ByteCount = iNumMidiBytes;
+ pos += sizeof(KSMUSICFORMAT);
+
+ // write MIDI bytes
+ if ( pos + iNumMidiBytes > data->m_Buffer.size() ) {
+ std::stringstream ost;
+ ost << "KsMidiInput::Write: MIDI buffer too small. Required " << pos + iNumMidiBytes << " bytes, only has " << data->m_Buffer.size();
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ if ( data->m_pPin == NULL ) {
+ std::stringstream ost;
+ ost << "MidiOutWinKS::sendMessage: port is not open";
+ errorString_ = ost.str();
+ RtMidi::error( RtError::WARNING, errorString_ );
+ }
+
+ memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes);
+ pos += iNumMidiBytes;
+
+ KSSTREAM_HEADER packet;
+ memset(&packet, 0, sizeof packet);
+ packet.Size = sizeof(packet);
+ packet.PresentationTime.Time = 0;
+ packet.PresentationTime.Numerator = 1;
+ packet.PresentationTime.Denominator = 1;
+ packet.Data = const_cast